5 ms·
Scala does this in two ways. For one-armed `if`: - The type must be `Unit` - Since `()` is the only value of type `Unit`, we can unambiguously infer that the
by chriswarbo 4y ago
Scala does this in two ways. For one-armed `if`:
- The type must be `Unit`
- Since `()` is the only value of type `Unit`, we can unambiguously infer that the `else` case must be `()`
- Since `Unit` conveys no information, there is never any reason to assign it to a variable
- The `Unit` type is commonly used to represent effects, like `print` (on the JVM it's equivalent to Java's `void` type)
These features conspire to make one-armed `if` expressions act like statements, since they will generally perform an effect and not be bound to a variable.
Scala also provides an `Option.when` method, e.g. `Option.when(x.hasFoo)(x.foo)`. This seems nicer than the `boolean.then` mentioned by the article, for a few reasons:
- The use of `Option` is explicit, rather than implicit
- The second argument of `Option.when` is passed by-name, so there's no need to manually wrap it in a closure/thunk
- masklinn 4y ago> Scala does this in two ways. For one-armed `if`: That is exactly what Rust does: error[E0317]: `if` may be missing an `else` clause --> src/main.rs:2:13 | 2 | if true { 42 }; | ^^^^^^^^^^--^^ | | | | | found here | expected integer, found `()` | = note: `if` expressions without `else` evaluate to `()` = help: consider adding an `else` block that evaluates to the expected type The "note" line spells it out clearly, although the line annotations are a bit unclear. > - The use of `Option` is explicit, rather than implicit There's nothing implicit about Option, it's literally the concrete return type of the function. That's like saying the boolean is implicit in Option::when. > - The second argument of `Option.when` is passed by-name, so there's no need to manually wrap it in a closure/thunk Rust does not have lazy arguments, arguments are always eagerly evaluated. Thus it needs one lazy version which takes a function (bool::then), and optionally one eager version which takes a value (that's bool::then_some).
- chriswarbo 4y ago> That is exactly what Rust does Cool, that's good to know (I've not used Rust (yet)) > There's nothing implicit about Option, it's literally the concrete return type of the function For context, I was referring to this paragraph in the article regarding `.then`: > I’m not a huge fan of the implicit introduction of the Option type. In a language like Rust, implicitly introducing Option is barely acceptable: Option is already a priveleged type, and ‘accidentally’ assigning such an optional if-expression to a variable will likely cause a type mismatch error, caught by the compiler. --- > Rust does not have lazy arguments, arguments are always eagerly evaluated. I thought as much, since it would be a glaring omission if Rust did have this feature but didn't use it for the argument of '.then' ;) It also makes sense given Rust's goals of low-level, high-performance, substructural-typing, etc.: if extra wrapping/unwrapping is needed, better to make it explicit (and enforced by the types), rather than have the compiler slowing things down without warning. Also, to be clear: the Scala version is actually pass-by-name, rather than lazy; e.g. the following function will evaluate its argument twice! def double(x: => Int): Int = x + x