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.
Vladimir Matveev
source share