A call pattern allows a call to be made within a pattern match.
A pattern x
(
P0
,
… ,
Pn
)
,
is matched against a value v
by calling
x
.unapply(
v
)
,
and matching each value published by that call against the tuple pattern
(
P0
,
… ,
Pn
)
.
If there is only one pattern P
, then P
is matched on its own, instead of using a tuple pattern.
If there are no patterns, a wildcard pattern is used.
If x
.unapply(
v
)
halts silently,
or halts without producing any matching values, then the match fails.
If multiple values are published and successfully match, then a multimatch occurs: the entire pattern succeeds multiple times. In a function call, the matching clause is executed multiple times, once for each match. In a sequential combinator, the right hand side is executed multiple times, once for each match. In a pruning combinator, one of the matches is chosen arbitrarily.
When an as pattern contains a call pattern, counterintuitive behavior may result. The as pattern will capture the value fragment before matching, so if a call pattern changes the value fragment, that change will not be captured by the as pattern. Avoid using call patterns within as patterns unless the value fragment is guaranteed to remain unchanged.
When a call pattern is matched against a type S
,
the unapply
member of the type S
must have the function type
lambda
(
T
)
::
(
T0
,
… ,
Tn
)
,
where S
is a subtype of T
.
Then each argument pattern Pi
is matched against the corresponding type Ti
,
producing typing contexts Γi. The typing context
produced by the whole match is the union of the contexts Γi.
{- Build up a small binary tree, then use call patterns to deconstruct the tree and extract its contents. -} type Tree = Node(_,_,_) | Empty() val l = Node(Empty(), 0, Empty()) val r = Node(Empty(), 2, Empty()) val t = Node(l,1,r) t >Node(l,j,r)> l >Node(_,i,_)> r >Node(_,k,_)> ( i | j | k ) {- OUTPUT:PERMUTABLE 0 1 2 -}
{- A user-defined call pattern match, using a record with an unapply member. The integer square root function, isqrt, returns the square root of a perfect square, and halts on any input that is not a perfect square. isqrt is then used to define a value 'square' that matches perfect squares. -} def isqrt(n) = if (n <: 0) then stop else ( val root = Floor(n ** 0.5) if (n = root*root) then root else stop ) val square = {. unapply = isqrt .} each([9, 12, 16, 24, 25]) >square(n)> n {- OUTPUT:PERMUTABLE: 3 4 5 -}
{- A user-defined call pattern match, using a record with an unapply member. The factors function publishes all nontrivial positive factors of its argument n (any factor greater than 1 and less than n) factors is then used to define a value 'multipleOf' that matches all nontrivial positive factors of an integer. -} def factors(n) if (n <: 0) = factors(-n) def factors(n) = for(2, n/2 + 1) >i> Ift(n % i = 0) >> i val multipleOf = {. unapply = factors .} 30 >multipleOf(n)> n {- OUTPUT:PERMUTABLE: 2 3 5 6 10 15 -}
Related Reference Topics
Related Tutorial Sections