Wildcard Patterns

Note: Pattern Matching support is currently only partway through it's planned feature support (and has some open bugs to be addressed). More to come!

The utility of Pattern Matching is dramatically increased by making use of wildcards. For example, they enable the below match with cases that only specify partial matches and then bind matched values to a variable:

Fig 1:


newtype Square : int
newtype Rectangle : struct {height: int, width: int}
newtype Line : int

consumer printShapeArea(shape: oneof<Square, Rectangle, Line>) {
  var area: int;
  match (shape) {
    case Rectangle({height = H:int, width = W:int}) -> area = H * W;
    case Square(W:int)                              -> area = W * W;
    case _                                          -> area = 0;
  }
  print("Area of {shape}: {area}");
}

printShapeArea(Square(2));
printShapeArea(Rectangle({height = 10, width = 10}));
printShapeArea(Line(2));

Output:

Area of Square(2): 4
Area of Rectangle({height = 10, width = 10}): 100
Area of Line(2): 0

The syntax W:int is a "wildcard binding" that matches any int value and declares a variable that the int will be assigned to in the case code block.

Case Ordering and Wildcards

Cases are semantically matched in the order that they appear in the source code. This means that it's possible to define unreachable cases if the cases above already cover the pattern:

Note: Claro's error messaging is a work in progress - the below error message will be improved.

Fig 2:


var t = (1, 2);
match (t) {
  case (1, 3) -> # ...
    print("(1, 3)");
  case (_, 2) -> # ...
    print("(_, 2)");
  case (1, 2) -> # <-- This is unreachable.
    print("(1, 2)");
  case _      -> # ...
    print("_");
}

Compilation Errors:

wildcards_EX2_example.claro:2: Illegal Duplicate Match Case: All case patterns should be unique within a match block.
match (t) {
       ^
1 Error

Simply changing the ordering of the cases above will fix this problem:

Fig 3:


var t = (1, 2);
match (t) {
  case (1, 3) -> print("(1, 3)");
  case (1, 2) -> print("(1, 2)");
  case (_, 2) -> print("(_, 2)");
  case _      -> print("_");
}

Output:

(1, 2)