Patterns

The following is a list of expressions that have special meaning when treated as a pattern, whether they're used in a message pattern role, or match:, or with =. They are always parsed as normal expressions, and usually converted into a Pattern at the macroexpansion phase, via to: Pattern.

See also: =, :=, Defining Methods.

Types of Patterns

_, foo, ...

Possibly-named wildcard matches.

Example:

> _ = 1
1
> a = 2
2
> a
2
1, 2/3, 4.0, $a, True, False, "foo", ...

Primitive literal values match only on themselves.

Example:

> 1 = 1
1
> 1 = 2
ERROR: <error @(pattern: <pattern 1> did-not-match: 2)>
> $a = $a
$a
> 2/3 = 2/3
2/3
> 4.0 = 4.0
4.0
> 4.0 = 4.000000000001
ERROR: <error @(pattern: <pattern 4.0> did-not-match: 4.000000000001)>
> "foo" = "foo"
"foo"
foo: pattern

A named pattern-match. Matches pattern, binding the value it matches to foo.

Example:

> (foo: 2) = 2
2
> foo
2
> (foo: 2) = 1
ERROR: <error @(pattern: <pattern (foo: 2)> did-not-match: 1)>
head . tail

Matches a non-empty list, matching its first value on head and the rest of it on tail.

Example:

> (x . xs) = [1, 2, 3]
[1, 2, 3]
> x
1
> xs
[2, 3]
[], [pattern, pattern-2], ...

Matches a list of fixed length, recursively matching each pattern on each of its values.

Example:

> [] = []
[]
> [a, b] = [1, 2]
[1, 2]
> [c, 4] = [3, 4]
[3, 4]
> [a, b, c]
[1, 2, 3]
(), (pattern, pattern-2), ...

Matches a tuple, recursively matching each pattern on each of its values.

Example:

> () = ()
()
> (a, b) = (1, 2)
(1, 2)
> (c, 4) = (3, 4)
(3, 4)
> [a, b, c]
[1, 2, 3]
@foo, @(foo: x), @(foo: x bar: _), ...

Matches a particle value. If it's a single particle, it does regular equality checking; if it's a keyword particle, it recursively pattern-matches the particle's values. A wildcard in a particle pattern matches placeholders, but no other pattern will.

Example:

> @foo = @foo
@foo
> @foo = @bar
ERROR: <error @(pattern: <pattern @foo> did-not-match: @bar)>
> @(foo: x) = @(foo: 2)
@(foo: 2)
> x
2
> @(foo: _) = @(foo: _)
@foo:
> @(foo: _) = @(foo: 2)
@(foo: 2)
> @(foo: 2) = @(foo: _)
ERROR: <error @(pattern: <pattern @(foo: 2)> did-not-match: @foo:)>
`a, `(1 + ~b), ...

Matches expression values recursively. Unquotes serve as named wildcard patterns, with the same recursive semantics as quasiquotation.

Example:

> `a = `a
'(a)
> `(1 + ~b) = '(1 + 2)
'(1 + 2)
> ``(1 + ~~c) = ``(1 + ~3)
'(`(1 + ~3))
> [b, c]
['(2), '(3)]
-> pattern

Matches any object delegating to something matching pattern. Often used to check if something is an "instance" of some object.

For primitive values, it checks if the value itself matches the pattern, so [1, 2] will match (-> List).

NOTE: This is only really useful in match: and in message patterns; when used with = the objects aren't evaluated.

Example:

> 1 match: { (-> Double) -> @nope; (-> Integer) -> @yep }
@yep
> [1, 2] match: { (-> [a, b]) -> @(yep: [b, a]) }
@(yep: [2, 1])
== pattern

Matches with strict equality only. This is different from regular matching as it doesn't follow delegates to see if objects match.

Example:

> X = Object clone
<object (delegates to 1 object)>
> X match: { (== X) -> @yep }
@yep
> X clone match: { (== X) -> @yep; _ -> @nope }
@nope
... pattern

Matches a variadic role, matching the list of values as pattern.

That is, with a single value given for a variadic role, pattern will be pattern-matching a list with that single value. A role with more than one value given, via tuples, is matched as a list containing all of the values. A role with zero values (the empty tuple, ()) is matched as an empty list.

Example:

> () match: { (... vs) -> vs }
[]
> () match: { (... []) -> "no values!" }
"no values!"
> 1 match: { (... vs) -> vs }
[1]
> (2, 3) match: { (... vs) -> vs }
[2, 3]

A Pattern's Object

The object onto which a method is inserted is determined by the type of the pattern in its message pattern's first role:

_, foo, bar, ...

Object

1, 2, ...

Integer

$a, $b, ...

Character

True, False

Boolean

1.0, 2.0, ...

Double

1/2, 3/4, ...

Rational

"", "foo", ...

String

head . tail, [], [pattern, pattern-2], ...

List

`x, `(1 + ~y), ...

Expression

@foo, @(bar: 2 baz: _), ...

Particle

foo: pattern

target of pattern

-> pattern

target of pattern

== pattern

target of pattern

... pattern

Object

Foo, Foo bar, { expr; expr-2 }, ...

the object itself, or the object yielded by the block's execution

Thus, 1 foo: $a := x is a definition placed on Integer, while (... args) foo is inserted on Object.

Note that roles beginning with a capital letter are assumed to be targeting a particular object. That is, Foo means the same as { Foo }, while foo is just a named wildcard targeting Object.

Example:

Foo bar := 1
Foo bar: baz := 1

Above, the first definition is placed on the particular object Foo (assuming it's defined), while the second definition is placed on the Foo object as well as Object (the second role, a named wildcard), binding the second role value as baz.

To define on a particular object that isn't capitalized, wrap it in a block:

Example:

foo bar := 1
{ foo } bar := 2
{ "hi" print; 1 + 1 } bar: Foo := 3

As in the first example, foo bar matches any object, while { foo } bar is only defined on foo (the result of the block's execution). { 1 + 1 } bar: Foo is defined on 2 and Foo.

Pattern Objects

On occasion you'll want to create a pattern-match from an expression, or use patterns manually, usually in macros you define. The following methods should come in handy.

Pattern  Object

A pattern you can use to match and deconstruct values.

Pattern Role  Object

A pattern for use in a message pattern.

Pattern Define  Object

A message pattern for use in a definition.

expr to: Pattern  Pattern
  | expr is-a?: Expression

Convert an expression to the pattern-match it represents.

If the expression cannot represent a pattern, @unknown-pattern: is signaled.

Example:

> '1 to: Pattern
<pattern 1>
> '(foo: [1, 2, x]) to: Pattern
<pattern (foo: [1, 2, x])>
> 'r"foo" to: Pattern
ERROR: <error @(unknown-pattern: '(r{foo}))>
expr to: Pattern Role  Pattern
  | expr is-a?: Expression

Convert an expression to the pattern-match it represents, as if it were a role in a message pattern. The main difference is that a capitalized dispatch is considered a "particlar object" rather than a named wildcard. See Syntax.

If the expression cannot represent a pattern, @unknown-pattern: is signaled.

Example:

> '1 to: Pattern Role
<pattern 1>
> 'Integer to: Pattern Role
<pattern Integer>
> '(foo: Integer) to: Pattern Role
<pattern (foo: Integer)>
expr to: Pattern Define  Pattern
  | expr is-a?: Expression

Convert an expression to a message pattern for a definition, using @(to: Pattern Role) for its targets.

If the expression cannot represent a message pattern, @unknown-pattern: is signaled.

Example:

> '(Integer + Double) to: Pattern Define
<pattern Integer + Double>
> '(1 sqrt) to: Pattern Define
<pattern 1 sqrt>
> '1 to: Pattern Define
ERROR: <error @(unknown-pattern: '(1))>
pat name  String
  | pat is-a?: Pattern

Yields the name of a named wildcard match or a single message pattern.

Example:

> ('a to: Pattern) name
"a"
> ('(1 sqrt) to: Pattern Define) name
"sqrt"
pat names  List
  | pat is-a?: Pattern

Yields the names in a keyword message pattern.

Example:

> ('(1 plus: Integer) to: Pattern Define) names
["plus"]
pat target  Pattern
  | pat is-a?: Pattern

Yields the target of a single message pattern.

Example:

> ('(1 sqrt) to: Pattern Define) target
<pattern 1>
pat targets  List
  | pat is-a?: Pattern

Yields the targets of a keyword message pattern.

Example:

> ('(1 plus: Integer) to: Pattern Define) targets
[<pattern 1>, <pattern Integer>]
pat match: v  in?: [@(ok: bindings), @none]
  | pat is-a?: Patterh

Attempts to match the value v with pattern pat. If value matches, the bindings from the match are yielded, wrapped in @ok:. Otherwise, @none is yielded.

Example:

> ('1 to: Pattern) match: 1
@(ok: <object (delegates to 1 object)>)
> ('1 to: Pattern) match: 2
@none
> ('[1, 2, a] to: Pattern) match: [1, 2, 3]
@(ok: <object (delegates to 1 object)>
        a := 3)
top match: pat on: v  v
  | pat is-a?: Pattern

Pattern-match pat on v, inserting the bindings into top. Similar to = and match:.

If the pattern-match fails, @pattern:did-not-match: is signaled.

Example:

> match: ('[1, a, b] to: Pattern) on: [1, 2, 3]
[1, 2, 3]
> this
<object (delegates to 1 object)>
  a := 2
  b := 3
> match: ('[1, a, b] to: Pattern) on: 2
ERROR: <error @(pattern: <pattern [1, a, b]> did-not-match: 2)>