google/comprehensive-rust

`let`...`else` example should demonstrate denesting

fw-immunant opened this issue · 1 comments

Often when teaching people are underwhelmed by the utility of the let...else construct. I also don't think it makes a huge amount of sense as presented. The current example consists of several repetitions of the admittedly awkward pattern

let s = if let Some(s) = maybe_string {
	s
} else {
	return Err(String::from("got None"));
};

which is improved by let...else, but is also not a terribly common pattern on its own, and as I understand things isn't really what motivated this control flow construct.

My understanding is that the real utility of let...else is that it allows to de-nest what would otherwise be a rightward-drifting nesting of if lets:

if let Some(x) = obtain_x() {
	if let Some(y) = x.obtain_y() {
		if let z = compute_z(x, y) {
			// work with z
		}
	}
}

Which can instead become:

let Some(x) = obtain_x() else { return }
let Some(y) = x.obtain_y() else { return }
let Some(z) = compute_z(x, y) else { return }
// work with z

I think this makes the utility of the construct more clear.

It seems like the hex_or_die_trying example is already partially rewritten to avoid the nesting. It would be more motivating as

if let Some(s) = maybe_string {
    if let Some(first_byte_char) = s.chars().next() {
        if let Some(digit) = first_byte_char.to_digit(16) {
...