Can someone explain if let?

I have just read this.
But I don't really get it.

Do you only use it if you want to output/use the content from in an Option type with some kind of error-handling?

fn main() {
    
    let x : Option<String> = Some("lol".to_string());
    let y : Option<String> = Some("lol".to_string());
    let z : Option<String> = Some("lol".to_string());
    
    //So this...
    match x {
        Some(a) => {
            println!("{}", a);
        },
        _ => {}
    }
    
    
    
    //Is exactly the same as this:
    if let Some(a) = y {
        println!("{}", a);
    }
    
    
    //But why wouldn't you just do this?:
    println!("{}", z.unwrap());
    
}

Would be cool if someone was able to explain this phenomenon noob-friendly with a few examples.
Thanks!

z.unwrap() will panic if z is None, while the other options will let the current function continue executing.

1 Like

So it's all about the error handling you can put in the else-statement?

There are also cases where None is not an error at all, so you don't need any error handling.

For example, consider this function that prints all the elements in a simple linked list:

struct Link {
    val: i32,
    next: Option<Box<Link>>,
}

fn print_all(node: &Link) {
    println!("{}", node.val);
    if let Some(rest) = &node.next {
        print_all(rest);
    }
}

If we change this to use node.next.unwrap(), then the program will panic when it gets to the last node (which doesn't have a next element).

1 Like

if let is not specific to Option. It works for any type, e.g., see this from my own code:

if let InputAxis::Emulated { pos, neg } = input_axis { ... }

You can't unwrap an InputAxis.

2 Likes

Does the section in the book on if let help?

By the way:

What do you think that should do when z is None? Evaluation order dictates that the println!() call must have its arguments ready by the time it is unconditionally executed. And unwrap() also unconditionally returns an inner value – it has to panic if the Option is None.

It seems to me you have a fundamental misunderstanding on expression evaluation – in particular, it's not magic, the compiler can't guess your intention, and more importantly, even if it tried to, it shouldn't actively alter the control flow just so that your function calls don't panic.