LEVIATHAN v962456e · 962456eee1

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