Why does Rust need `if let` syntax?

Coming from other functional languages ​​(and being a newbie to Rust), I'm a little surprised at the motivation behind the Rust if let syntax. The RFC mentions that without if let "the idiomatic solution today is to test and deploy Option<T> " either

 match opt_val { Some(x) => { do_something_with(x); } None => {} } 

or

 if opt_val.is_some() { let x = opt_val.unwrap(); do_something_with(x); } 

In Scala, one could do the same. But the idiomatic solution is rather equal to map compared to Option (or before foreach , if it is only for the side effect of doing_something_with(x) ).

So my question is: why is this not an idiomatic solution to do the same in Rust:

 opt_val.map(|x| do_something_with(x)); 
+7
option rust
source share
3 answers

.map() specific to the Option<T> , but if let (and while let !!) are functions that work with all types of Rust.

+8
source share

map() intended to convert an optional value, while if let is mainly required to perform side effects. Although Rust is not a pure language, so any of its code blocks may contain side effects, map semantics still exist. Using map() to do side effects is certainly only possible for confusing readers of your code. Note that it should not have performance penalties, at least in simple code. The LLVM optimizer is perfectly capable of embedding the closure directly in the calling function, so it becomes equivalent to the match statement.

Prior to if let only way to perform side effects on Option was either by coincidence or if with the Option::is_some() tag. The match approach is the safest, but it is very verbose, especially if you need a lot of nested checks:

 match o1 { Some(v1) => match v1.f { Some(v2) => match some_function(v2) { Some(r) => ... None => {} } None => {} } None => {} } 

Notice the prominent right drift and a lot of syntax noise. And it only worsens if the branches are not simple coincidences, but correct blocks with several statements.

An approach

if option.is_some() , on the other hand, is a little less verbose, but still very poorly read. Also, state checking and unwrap() not statically bound, so you could be wrong if the compiler did not notice this.

if let solves the problem of verbosity, based on the same pattern matching infrastructure as match (so it’s harder to make mistakes than if option.is_some() ), and as a side benefit it allows you to use arbitrary types in templates, not just Option . For example, some types may not provide map() -like methods; if let will work with them very well. So, if let is a clear gain, therefore, it is idiomatic.

+13
source share

Because your solution creates a closure that uses resources, while if let desugars exactly matches your first example, which is not the case. I also find it more readable.

Rust is a zero-cost abstraction that makes programming more enjoyable, and if let and while let are good examples of these (at least IMO - I understand this is a matter of personal preference). They are not strictly necessary, but they certainly feel good (see also: Clojure, where they were probably filmed).

+2
source share

All Articles