leviathan-lang.com / docs / learn
Pattern matching
Dispatching on values, ranges, types, and enum members with match.
Matching values and ranges
match dispatches on a type or a value in one readable construct. It is an expression when its
arms yield a value, and a statement otherwise. First match wins. A range arm lo..hi includes
both ends.
Range arms
string grade(int score) => match (score) {
90..100 => "A";
80..89 => "B";
70..79 => "C";
else => "F";
};
console.writeln(grade(95));
console.writeln(grade(85));
console.writeln(grade(72));
console.writeln(grade(10));
A
B
C
F
Matching on type
Matching on type narrows the subject inside each arm, the same machinery as is and catch. An
arm names the type alone, and inside it the subject has that type:
Type arms narrow the subject
interface IShape { }
class Circle : IShape { public int radius; }
class Square : IShape { public int side; }
class Blob : IShape { }
string describe(IShape sh) => match (sh) {
Circle => "circle r=${sh.radius}"; // sh is a Circle here
Square => "square ${sh.side}"; // sh is a Square here
else => "shape";
};
console.writeln(describe(Circle(3)));
console.writeln(describe(Square(4)));
console.writeln(describe(Blob()));
circle r=3
square 4
shape
Exhaustive over enums
Over an enum, match is exhaustive: cover every member and you need no else. Omitting one is
a compile error that names what you missed.
No else needed when every member is covered
enum Method { GET, HEAD, POST }
string verb(Method m) => match (m) {
Method::GET => "read";
Method::HEAD => "peek";
Method::POST => "write";
}; // exhaustive: no else needed
console.writeln(verb(Method::GET));
console.writeln(verb(Method::POST));
read
write