## Pattern Forms

This page describes all the forms that patterns can take in Cyclone. For each pattern form, you need to know:

- The syntax
- The types of expressions it can match against (to avoid a compile-time error)
- The expressions the pattern matches against (other expressions cause a match failure)
- The bindings the pattern introduces, if any.

There is one compile-time rule that is the same for all forms: All variables (and type variables) in a pattern must be distinct. For example, “let Pair(fst,fst) = pr;” is not allowed.

You may want to read the descriptions for variable and struct patterns first because we have already explained their use informally.

**Variable patterns**- Syntax: an identifer
- Types for match: all types
- Expressions matched: all expressions
- Bindings introduced: the identifier is bound to the expression being matched

**Wildcard patterns**- Syntax: _ (underscore, note this use is completely independent of _ for [type inference][13])
- Type for match: all types
- Expressions matched: all expressions
- Bindings introduced: none. Hence it is like a variable pattern that uses a fresh identifier. Using _ is better style because it indicates the value matched is not used. Notice that “let _ = e;” is equivalent to e.

**As patterns**- Syntax: x as p where x is an identifier and p is a pattern.
- Types for match: all types
- Expressions matched: all expressions
- Bindings introduced: if the expression matches the pattern p, then its value is bound to x. Thus, a variable pattern is simply shorthand for “x as _”.

**Reference patterns**- Syntax: *x (i.e., the * character followed by an identifier)
- Types for match: all types
- Expressions matched: all expressions. (Very subtle notes: Currently, reference patterns may only appear inside of other patterns so that the compiler can determine the region for the pointer type assigned to x. They also may not occur under a datatype pattern that has existential types unless there is a pointer pattern in-between.)
- Bindings introduced: x is bound to
*the address of*the expression being matched. Hence if matched against a value of type t in region`r, the type of x is t@`

r.

**Numeric constant patterns**- Syntax: An int, char, or float constant
- Types for match: numeric types
- Expressions matched: numeric values such that == applied to the value and the pattern yields true. (Standard C numeric promotions apply. Note that comparing floating point values for equality is usually a bad idea.)
- Bindings introduced: none

**NULL******constant patterns**- Syntax: NULL
- Types for match: nullable pointer types, including ? types
- Expressions matched: NULL
- Bindings introduced: none

**Enum patterns**- Syntax: an enum constant
- Types for match: the enum type containing the constant
- Expressions matched: the constant
- Bindings introduced: none

**Tuple patterns**Syntax: $(p1,…,pn[,…]) where p1,…,pn are patterns. The trailing comma and ellipses (…) are optional.

Types for match: if no ellipses, then tuple types with exactly n fields, where pi matches the type of the tuple’s ith field. If the ellipses are present, then matches a tuple with at least n fields.

- Expressions matched: tuples where the ith field matches pi for i between 1 and n.
- Bindings introduced: bindings introduced by p1, …, pn.

**Struct patterns**Syntax: There are three forms:

X(p1,…,pn[,…]) where X is the name of a struct with n fields and p1,…,pn are patterns. This syntax is shorthand for

`X{.f1 = p1, ..., .fn = pn [,...]}`

where fi is the ith field in X.`X{.f1 = p1, ..., .fn = pn [,...]}`

where the fields of X are f1, …, fn but not necessarily in that order`{.f1 = p1, ..., .fn = pn [,...]}`

which is the same as above except that struct name X has been omitted.

Types for match: struct X (or instantiations when struct X is polymorphic) such that pi matches the type of fi for i between 1 and n. If the ellipses are not present, then each member of the struct must have a pattern.

- Expressions matched: structs where the value in fi matches pi for i between 1 and n.
- Bindings introduced: bindings introduced by p1,…,pn

**Tagged Union patterns**Syntax: There are two forms:

`X{.fi = p}`

where the members of X are f1, …, fn and fi is one of those members.`{{.f1 = p`

which is the same as above except that union name X has been omitted.

Types for match: union X (or instantiations when union X is polymorphic) such that p matches the type of fi.

- Expressions matched: tagged unions where the last member written was fi and the value of that member matches p.
- Bindings introduced: bindings introduced by p.

**Pointer patterns**- Syntax: &p where p is a pattern
- Types for match: pointer types, including ? types. Also datatype Foo @ (or instantiations of it) when the pattern is &Bar(p1,…,pn) and Bar is a variant of datatype Foo and pi matches the type of the ith value carried by Bar.
- Expressions matched: non-null pointers where the value pointed to matches p. Note this explanation includes the case where the expression has type datatype Foo @ and the pattern is &Bar(p1,…,pn) and the current variant of the expression is “pointer to Bar”.
- Bindings introduced: bindings introduced by p

**Datatype patterns**- Syntax: X if X is a variant that carries no values. Else X(p1,…,pn[,…]) where X is the name of a variant and p1, …, pn are patterns. As with tuple and struct patterns, the ellipses are optional.
- Types for match: datatype Foo (or instantiations of it).
- Expressions matched: If X is non-value-carrying, then X. If X is value-carrying, then values created from the constructor X such that pi matches the ith field.
- Bindings introduced: bindings introduced by p1,…,pn