Language Design: Unified Condition Syntax
Idea
Replace the different syntactic forms of
- if expressions,
- pattern matching and pattern guards,
- if-let constructs
with a single, unified condition syntax that scales from simple one-liners to complex pattern matches.
Motivation
The intention is to cut the different syntax options down to a single one that is still easily recognizable by users,
not to minimize keywords (i. e. a == b then c else d) or turn conditions into methods (like Smalltalk).
Principles
- The condition can be split between a common discriminator and individual cases.
- This requires doing away with mandatory parentheses around the conditions.
- This strongly suggests using a keyword (
then) to introduce branches, instead of using curly braces, based on readability considerations.
- The keyword
ifis chosen over other options likematch,when,switchorcasebecause it is keyword the largest number of developers are familiar with.
Examples
The following examples assume that the language has indentation-sensitive syntax to ensure unambiguous parsing.
Languages without indentation-sensitve syntax require either mandatory braces around the bodies of then branches, or ending then branches explicitly, for instance with end or a ,.
simple if expression
if x == 1.0 /* same as */
then "a" if x == 1.0 then "a" else "z"
else "z"
one comparison operator on multiple targets
if x == if x /* same as */
1.0 then "a" == 1.0 then "a" if x == 1.0 then "a"
2.0 then "b" == 2.0 then "b" else if x == 2.0 then "b"
else "z" else "z" else "z"
different comparison operators, equality and identity
if x /* same as */
== 1.0 then "a" if x == 1.0 then "a"
eq NaN then "n" else if x eq NaN then "b"
else "z" else "z"
method calls
if xs /* same as */
.isEmpty then "e" if xs.isEmpty then "e"
.contains(0.0) then "n" else if xs.contains(0.0) then "n"
else "z" else "z"
pattern matching (is), introducing bindings (@)
if alice
.age < 18 then "18"
is Person("Alice", age@) then "$age"
is person@Person("Bob", _) then "{$person.age}"
else "0"
pattern matching using “if-let”12
if person is Person("Alice", age@)
then "$age"
else "o"
wildcards (_) and pattern guards
if person
is Person("Alice", _) then "alice"
is Person(_, age@) && age >= 18 then "adult"
else "minor"
Further Considerations
A reasonable question that might be asked is whether this design can be extended to also handle thrown exceptions,
and whether such an extension could completely replace the try-catch-finally idiom.
One language that has done something similar is Ocaml, which has extended its pattern matching syntax/semantics.
One option might be something along the lines of
if readPersonFromFile(file)
throws[IOException](ex@) then "unknown, due to $ex"
is Person("Alice", _) then "alice"
is Person(_, @age) && age >= 18 then "adult"
else "minor"
This might require adding some amount of language magic to deal with the throws construct though, depending on the expressiveness of the core language.
Related Work
- Haskell – multi-way if-expressions
- CommonLisp – cond and case