On this page:
match
matches
_
where
where
8.12

6.14 Matching🔗ℹ

expression

match target_expr

| bind:

    result_body

    ...

| ...

 

expression

match target_expr

| bind:

    result_body

    ...

| ...

| ~else:

    result_body

    ...

 

expression

match target_expr

| bind:

    result_body

    ...

| ...

| ~else result_expr

Tries matching the result of target_expr against each bind in sequence, and as soon as one matches, returns the result of the corresponding result_body block. The keyword ~else can be used as a synonym for _ (which matches any value without binding any identifiers) in the last clause.

Typically, a bind imposes requires on a value and binds some number of identifiers as a result of a successful match. For example, a literal number works as a bind pattern, but it binds zero identifiers. An identifier as a bind pattern matches any value and binds the identifier the the matching value. A list form is a bind pattern with subpatterns as its elements, and it matches a list with the right number of elements that match match the corresponding pattern. A when or unless can impose a side condition on a match. The set of bind forms is extensible, so it cannot be completely enumerated here.

If no target_expr produces a true value and there is no ~else clause, a run-time exception is thrown. In that case, when all of the bind forms are syntax-object patterns, the generated exception’s message may be specialized to report the expected pattern, instead of just reporting that no cases matched.

If an initial segment of bind patterns are literals or combinations of literals with ||, then the match is implemented as a case dispatch, and a match is found with logarithmic rather than linear time complexity in the number of literals. The remaining patterns are handled as usual.

> match 1+2

  | 3: "three"

  | ~else: "not three"

"three"

> match [1+2, 3+4]

  | [x, y]: x+y

10

> match 'go ~slow'

  | 'go ~fast': "ok"

match: expected the keyword ~fast

> match 1+2

  | n when n > 4: "ok"

match: no matching case

expression

expr matches bind

Produces #true if the value of expr matches bind, #false otherwise. Equivalent to expr is_a matching(bind).

> [1, 2, 3] matches [_, _, _]

#true

> [1, 2, 3] is_a matching([_, _, _])

#true

binding operator

_

Matches any value without binding any identifiers.

> match 1+2

  | 0: "zero"

  | _: "nonzero"

"nonzero"

binding operator

left_bind where right_bind = expr

 

binding operator

left_bind where:

  right_bind_and_expr

  ...

 

right_bind_and_expr

 = 

right_bind = expr

 | 

right_bind:

  body

  ...

Creates a binding that matches only when both left_bind matches and when each right_bind matches the value of the corresponding expr or body sequence. Names bound by left_bind and each right_bind are visible in exprs and body sequences for subsequent right_binds.

The where form should generally be used with parentheses around it, since parsing is otherwise likely to interact badly with the enclosing context, such as conflicting interpretations of a = by where and def.

> def ([x, y, z] where sum = x+y+z) = [1, 2, 3]

> '$x $y $z'

'1 2 3'

> sum

6

fun

| f(([x, y, z] where sum = x+y+z) when sum == 6):

    '$x $y $z = $sum'

| f(_):

    "something else"

> f([1, 2, 3])

'1 2 3 = 6'

> f([0, 2, 3])

"something else"

> def ([x, y, z] where:

         partial_sum = x+y

         sum = partial_sum+z):

    [1, 2, 3]

> sum

6

> def ([xs] where [x, ...] = xs) = [[1, 2, 3]]

> '$x ...'

'1 2 3'

> def ([xs] where [x, ...] = xs) = ["oops"]

def: value does not satisfy annotation

  value: ["oops"]

  position: 1st

  annotation: matching(List(_)) where ....

expression

where

 

expression

left_bind where

As an expression operator, where always reports a syntax error.