if-else chains considered harmful
As always, I have some strong opinions on things I probably shouldn’t have opinions on. This time I want to tell you why I think if
-else
chains are syntactically harmful.
I think that the syntax for if-else chains that are used in most imperative languages, including Rust, is bad.
if something.something() {
do_something()
} else if let Some(x) = get_x() {
use_x(x);
} else if mutliline {
a();
b();
c();
} else {
scream("aaaaaaaaaaaaaaaaaaaaaaa")?;
}
It’s hard to read:
-
conditions are mixed with
if
/else
/let
keyword-noise[else] if let
in Rust allows pattern-matching behaviour inif
statements -
conditions are indented more than expressions
-
conditions are indented inconsistently between the first branch (
if
) and the following ones (else if
) -
one-liners take a lot of lines
-
etc.
Singular if
s are fine I guess, it’s the else if
chains that make all of this particularly bad
I think that a much better way to model the same thing is when
from Kotlin or pattern guards/multi-way-if from Haskell.
Kotlin and Haskell examples
when {
x.isOdd() -> print("x is odd")
y.isEven() -> print("y is even")
else -> print("x+y is odd")
}
case () of _
| condition1 -> expr1
| condition2 -> expr2
| condition3 -> expr3
| otherwise -> default
if | condition1 -> expr1
| condition2 -> expr2
| condition3 -> expr3
| otherwise -> default
In Rust this can be simulated via match
on unit with pattern guards (Boxy style):
match () {
_ if something.something() => do_something(),
_ if let Some(x) = get_x() => use_x(x),
_ if multiline => {
a();
b();
c();
}
_ => scream("aaaaaaaaaaaaaaaaaaaaaaa")?,
}
But this is still messy, if let
guards are unstable and the repeated if
s are still there.
This is why I created kiam
(#shamelessplug?) — a crate that provides a simple macro that makes these chains a lot nicer:
when! {
something.something() => do_something(),
let Some(x) = get_x() => use_x(x),
multiline => {
a();
b();
c();
}
_ => scream("aaaaaaaaaaaaaaaaaaaaaaa")?,
}
I’ve explained kiam
with memes on twitter dot com
One of the only downsides of when!
is IDE and tooling (rustfmt
) support (or rather the absence of it). I wish this was part of the language or std…
Soooo yeah, there isn’t much to add here. If-else chains are bad for humans, macros are bad for IDEs, I have a cool crate.
Bye.