Yeah both are examples of the designer being a bit &quot;cute&quot;. The piston thing is however totally idiomatic and recommended by the piston devs, while I&#x27;ve never seen anyone actually loop over an Option in real code.<p>Though it wouldn&#x27;t be super terrible if it was idiomatic. I personally prefer to do `s.map(|val| { ... }), but there&#x27;s a contingent that argues that `map` shouldn&#x27;t be used purely for side-effects, and should instead be used for, you know, mapping. We&#x27;ve oft argued that if you want to consume an iterator, it aught to be with a `for` loop, so it might make sense to say the same about an Option? Option is such a trivial and core type that you basically end up with 4 ways to do everything you could think of, because semantically distinct conventions all end up doing the exact same thing:<p><pre><code>    for x in data { 
        println!(&quot;{}&quot;, x) 
    }
    
    if let Some(x) = data { 
        println!(&quot;{}&quot;, x) 
    }
    
    data.map(|x| {
        println!(&quot;{}&quot;, x)
    });
    
    match data { 
        Some(x) =&gt; println!(&quot;{}&quot;, x), 
        _ =&gt; () 
    }

</code></pre>
The fact that you can loop over an option is kind of a side-effect of a lot of our APIs taking &quot;thing that is iterable&quot;, and evidently it was convenient to provide that for Option (which is after all just a really degenerate collection).<p>You can of course `match` and `if let` an Option because it&#x27;s an enum, but because there&#x27;s two cases and one has no state, they end up being completely equivalent (the `_ =&gt;` branch is just an `else`).<p>Then finally you can `map` over an Option because... It&#x27;s Option. That&#x27;s what you do with optional types, dangit!