Using closures to avoid runtime evaluation
Sometimes, it might seem natural to write code that does not perform as fast as expected. Many times, this is due to Rust doing some extra computations at runtime. An example of an unnecessary computation that someone could write is the following:
let opt = Some(123);
let non_opt = opt.unwrap_or(some_complex_function());
I have intentionally made this example simply because a real example usually takes really long code. The idea behind it is valid though. When you have an Option or a Result, you have some very useful functions to allow you get the value inside or a default. There is this specific function, the unwrap_or() function, that allows you specify the default value. Of course, you can pass anything you want to that function, but if you require a complex calculation to calculate the default value (and it's not a constant), the code will perform poorly.
This happens because when calling the unwrap_or() function, the value you pass must be calculated beforehand. This does not make much sense if most of the time the value will exist and the computation is not required. A better option is to use unwrap_or_else(). This function accepts a closure that will only be executed if the Option/Result is None/Err respectively. In this concrete case, since some_complex_function() does not have any arguments, you can directly use that as the closure:
let opt = Some(123);
let non_opt = opt.unwrap_or_else(some_complex_function);
But if the function requires arguments, you will need to build the closure yourself:
let opt = Some(123);
let non_opt = opt.unwrap_or_else(|| {
even_more_complex_function(get_argument())
});
This way, you can use a very complicated function, as complicated as you'd like, and you will avoid calling it if there is something inside the Option type. You will also reduce the cyclomatic complexity of the function.