Pattern Matching

Patterns

  Pattern         ::=  Pattern1 { ‘|’ Pattern1 }
  Pattern1        ::=  boundvarid ‘:’ TypePat
                    |  ‘_’ ‘:’ TypePat
                    |  Pattern2
  Pattern2        ::=  id [‘@’ Pattern3]
                    |  Pattern3
  Pattern3        ::=  SimplePattern
                    |  SimplePattern {id [nl] SimplePattern}
  SimplePattern   ::=  ‘_’
                    |  varid
                    |  Literal
                    |  StableId
                    |  StableId ‘(’ [Patterns] ‘)’
                    |  StableId ‘(’ [Patterns ‘,’] [id ‘@’] ‘_’ ‘*’ ‘)’
                    |  ‘(’ [Patterns] ‘)’
                    |  XmlPattern
  Patterns        ::=  Pattern {‘,’ Patterns}

A pattern is built from constants, constructors, variables and type tests. Pattern matching tests whether a given value (or sequence of values) has the shape defined by a pattern, and, if it does, binds the variables in the pattern to the corresponding components of the value (or sequence of values). The same variable name may not be bound more than once in a pattern.

Example

Some examples of patterns are:

  1. The pattern ex: IOException matches all instances of class IOException, binding variable ex to the instance.
  2. The pattern Some(x) matches values of the form Some(vv), binding x to the argument value vv of the Some constructor.
  3. The pattern (x, _) matches pairs of values, binding x to the first component of the pair. The second component is matched with a wildcard pattern.
  4. The pattern x :: y :: xs matches lists of length 2\geq 2, binding x to the list's first element, y to the list's second element, and xs to the remainder.
  5. The pattern 1 | 2 | 3 matches the integers between 1 and 3.

Pattern matching is always done in a context which supplies an expected type of the pattern. We distinguish the following kinds of patterns.

Variable Patterns

  SimplePattern   ::=  ‘_’
                    |  varid

A variable pattern xx is a simple identifier which starts with a lower case letter. It matches any value, and binds the variable name to that value. The type of xx is the expected type of the pattern as given from outside. A special case is the wild-card pattern _ which is treated as if it was a fresh variable on each occurrence.

Typed Patterns

  Pattern1        ::=  varid ‘:’ TypePat
                    |  ‘_’ ‘:’ TypePat

A typed pattern x:Tx: T consists of a pattern variable xx and a type pattern TT. The type of xx is the type pattern TT, where each type variable and wildcard is replaced by a fresh, unknown type. This pattern matches any value matched by the type pattern TT; it binds the variable name to that value.

Pattern Binders

  Pattern2        ::=  varid ‘@’ Pattern3

A pattern binder xx@pp consists of a pattern variable xx and a pattern pp. The type of the variable xx is the static type TT implied by the pattern pp. This pattern matches any value vv matched by the pattern pp, and it binds the variable name to that value.

A pattern pp implies a type TT if the pattern matches only values of the type TT.

Literal Patterns

  SimplePattern   ::=  Literal

A literal pattern LL matches any value that is equal (in terms of ==) to the literal LL. The type of LL must conform to the expected type of the pattern.

Interpolated string patterns

  Literal  ::=  interpolatedString

The expansion of interpolated string literals in patterns is the same as in expressions. If it occurs in a pattern, a interpolated string literal of either of the forms

id"text0{ pat1 }text1 … { patn }textn"
id"""text0{ pat1 }text1 … { patn }textn"""

is equivalent to:

StringContext("""text0""", …, """textn""").id(pat1, …, patn)

You could define your own StringContext to shadow the default one that's in the scala package.

This expansion is well-typed if the member id evaluates to an extractor object. If the extractor object has apply as well as unapply or unapplySeq methods, processed strings can be used as either expressions or patterns.

Taking XML as an example

implicit class XMLinterpolation(s: StringContext) = {
    object xml {
        def apply(exprs: Any*) =
            // parse ‘s’ and build an XML tree with ‘exprs’ 
            //in the holes
        def unapplySeq(xml: Node): Option[Seq[Node]] =
          // match `s’ against `xml’ tree and produce 
          //subtrees in holes
    }
}

Then, XML pattern matching could be expressed like this:

case xml"""
      <body>
        <a href = "some link"> $linktext </a>
      </body>
     """ => ...

where linktext is a variable bound by the pattern.

Stable Identifier Patterns

  SimplePattern   ::=  StableId

A stable identifier pattern is a stable identifier rr. The type of rr must conform to the expected type of the pattern. The pattern matches any value vv such that rr == vv (see here).

To resolve the syntactic overlap with a variable pattern, a stable identifier pattern may not be a simple name starting with a lower-case letter. However, it is possible to enclose such a variable name in backquotes; then it is treated as a stable identifier pattern.

Example

Consider the following class definition:

class C { c =>
  val x = 42
  val y = 27
  val Z = 8
  def f(x: Int) = x match {
    case c.x => 1  // matches 42
    case `y` => 2  // matches 27
    case Z   => 3  // matches 8
    case x   => 4  // matches any value
  }
}

Here, the first three patterns are stable identifier patterns, while the last one is a variable pattern.

Constructor Patterns

SimplePattern   ::=  StableId ‘(’ [Patterns] ‘)’

A constructor pattern is of the form c(p1,,pn)c(p_1 , \ldots , p_n) where n0n \geq 0. It consists of a stable identifier cc, followed by element patterns p1,,pnp_1 , \ldots , p_n. The constructor cc is a simple or qualified name which denotes a case class. If the case class is monomorphic, then it must conform to the expected type of the pattern, and the formal parameter types of xx's primary constructor are taken as the expected types of the element patterns p1,,pnp_1, \ldots , p_n. If the case class is polymorphic, then its type parameters are instantiated so that the instantiation of cc conforms to the expected type of the pattern. The instantiated formal parameter types of cc's primary constructor are then taken as the expected types of the component patterns p1,,pnp_1, \ldots , p_n. The pattern matches all objects created from constructor invocations c(v1,,vn)c(v_1 , \ldots , v_n) where each element pattern pip_i matches the corresponding value viv_i.

A special case arises when cc's formal parameter types end in a repeated parameter. This is further discussed here.

Tuple Patterns

  SimplePattern   ::=  ‘(’ [Patterns] ‘)’

A tuple pattern (p1,,pnp_1 , \ldots , p_n) is an alias for the constructor pattern scala.Tuplenn(p1,,pnp_1 , \ldots , p_n), where n2n \geq 2. The empty tuple () is the unique value of type scala.Unit.

Extractor Patterns

  SimplePattern   ::=  StableId ‘(’ [Patterns] ‘)’

An extractor pattern x(p1,,pn)x(p_1 , \ldots , p_n) where n0n \geq 0 is of the same syntactic form as a constructor pattern. However, instead of a case class, the stable identifier xx denotes an object which has a member method named unapply or unapplySeq that matches the pattern.

An extractor pattern cannot match the value null. The implementation ensures that the unapply/unapplySeq method is not applied to null.

A type is said to be an extractor type for some type T if it has a method get with return type T, and a method isEmpty with a return type that conforms to Boolean. Option[T] is an extractor type for type T.

An unapply method in an object xx matches the pattern x(p1,,pn)x(p_1 , \ldots , p_n) if it has a single parameter (and, optionally, an implicit parameter list) and one of the following applies:

An unapplySeq method in an object xx matches the pattern x(q1,,qm,p1,,pn)x(q_1 , \ldots , q_m, p_1 , \ldots , p_n) if it takes exactly one argument and its result type is of the form Option[(T1,,TmT_1 , \ldots , T_m, Seq[S])] (if m = 0, the type Option[Seq[S]] is also accepted). This case is further discussed below.

Example 1

If we define an extractor object Pair:

object Pair {
  def apply[A, B](x: A, y: B) = Tuple2(x, y)
  def unapply[A, B](x: Tuple2[A, B]): Option[Tuple2[A, B]] = Some(x)
}

This means that the name Pair can be used in place of Tuple2 for tuple formation as well as for deconstruction of tuples in patterns. Hence, the following is possible:

val x = (1, 2)
val y = x match {
  case Pair(i, s) => Pair(s + i, i * i)
}
Example 2

If we define a class NameBased

class NameBased[A, B](a: A, b: B) {
  def isEmpty = false
  def get = this
  def _1 = a
  def _2 = b
}

Then NameBased is an extractor type for NameBased itself, since it has a member isEmpty returning a value of type Boolean, and it has a member get returning a value of type NameBased.

Since it also has members _1 and _2, it can be used in an extractor pattern with n = 2 as follows:

object Extractor {
  def unapply(x: Any) = new NameBased(1, "two")
}

"anything" match {
  case Extractor(a, b) => println(s"\$a, \$b") //prints "1, two"
}

Pattern Sequences

SimplePattern ::= StableId ‘(’ [Patterns ‘,’] [varid ‘@’] ‘_’ ‘*’ ‘)’

A pattern sequence p1,,pnp_1 , \ldots , p_n appears in two contexts. First, in a constructor pattern c(q1,,qm,p1,,pn)c(q_1 , \ldots , q_m, p_1 , \ldots , p_n), where cc is a case class which has m+1m+1 primary constructor parameters, ending in a repeated parameter of type S*. Second, in an extractor pattern x(q1,,qm,p1,,pn)x(q_1 , \ldots , q_m, p_1 , \ldots , p_n) if the extractor object xx does not have an unapply method, but it does define an unapplySeq method with a result type that is an extractor type for type (T_1, ... , T_m, Seq[S]) (if m = 0, an extractor type for the type Seq[S] is also accepted). The expected type for the patterns pip_i is SS.

The last pattern in a pattern sequence may be a sequence wildcard _*. Each element pattern pip_i is type-checked with SS as expected type, unless it is a sequence wildcard. If a final sequence wildcard is present, the pattern matches all values vv that are sequences which start with elements matching patterns p1,,pn1p_1 , \ldots , p_{n-1}. If no final sequence wildcard is given, the pattern matches all values vv that are sequences of length nn which consist of elements matching patterns p1,,pnp_1 , \ldots , p_n.

Infix Operation Patterns

  Pattern3  ::=  SimplePattern {id [nl] SimplePattern}

An infix operation pattern p;op;qp;\mathit{op};q is a shorthand for the constructor or extractor pattern op(p,q)\mathit{op}(p, q). The precedence and associativity of operators in patterns is the same as in expressions.

An infix operation pattern p;op;(q1,,qn)p;\mathit{op};(q_1 , \ldots , q_n) is a shorthand for the constructor or extractor pattern op(p,q1,,qn)\mathit{op}(p, q_1 , \ldots , q_n).

Pattern Alternatives

  Pattern   ::=  Pattern1 { ‘|’ Pattern1 }

A pattern alternative p1p_1 | \ldots | pnp_n consists of a number of alternative patterns pip_i. All alternative patterns are type checked with the expected type of the pattern. They may not bind variables other than wildcards. The alternative pattern matches a value vv if at least one its alternatives matches vv.

XML Patterns

XML patterns are treated here.

Regular Expression Patterns

Regular expression patterns have been discontinued in Scala from version 2.0.

Later version of Scala provide a much simplified version of regular expression patterns that cover most scenarios of non-text sequence processing. A sequence pattern is a pattern that stands in a position where either (1) a pattern of a type T which is conforming to Seq[A] for some A is expected, or (2) a case class constructor that has an iterated formal parameter A*. A wildcard star pattern _* in the rightmost position stands for arbitrary long sequences. It can be bound to variables using @, as usual, in which case the variable will have the type Seq[A].

Irrefutable Patterns

A pattern pp is irrefutable for a type TT, if one of the following applies:

  1. pp is a variable pattern,
  2. pp is a typed pattern x:Tx: T&#x27;, and T&lt;:TT &lt;: T&#x27;,
  3. pp is a constructor pattern c(p1,,pn)c(p_1 , \ldots , p_n), the type TT is an instance of class cc, the primary constructor of type TT has argument types T1,,TnT_1 , \ldots , T_n, and each pip_i is irrefutable for TiT_i.
  4. pp is an extractor pattern for which the extractor type is Some[TT] for some type TT
  5. pp is an extractor pattern for which the extractor types isEmpty method is the singleton type false
  6. pp is an extractor pattern for which the return type is the singleton type true

Type Patterns

  TypePat           ::=  Type

Type patterns consist of types, type variables, and wildcards. A type pattern TT is of one of the following forms:

The bottom types scala.Nothing and scala.Null cannot be used as type patterns, because they would match nothing in any case.

Types which are not of one of the forms described above are also accepted as type patterns. However, such type patterns will be translated to their erasure. The Scala compiler will issue an "unchecked" warning for these patterns to flag the possible loss of type-safety.

A type variable pattern is a simple identifier which starts with a lower case letter.

Type Parameter Inference in Patterns

Type parameter inference is the process of finding bounds for the bound type variables in a typed pattern or constructor pattern. Inference takes into account the expected type of the pattern.

Type parameter inference for typed patterns

Assume a typed pattern p:Tp: T&#x27;. Let TT result from TT&#x27; where all wildcards in TT&#x27; are renamed to fresh variable names. Let a1,,ana_1 , \ldots , a_n be the type variables in TT. These type variables are considered bound in the pattern. Let the expected type of the pattern be pt\mathit{pt}.

Type parameter inference constructs first a set of subtype constraints over the type variables aia_i. The initial constraints set C0\mathcal{C}_0 reflects just the bounds of these type variables. That is, assuming TT has bound type variables a1,,ana_1 , \ldots , a_n which correspond to class type parameters a1,,ana_1&#x27; , \ldots , a_n&#x27; with lower bounds L1,,LnL_1, \ldots , L_n and upper bounds U1,,UnU_1 , \ldots , U_n, C0\mathcal{C}_0 contains the constraints

{ai&lt;:σUi(i=1,,n)σLi&lt;:ai(i=1,,n) \begin{cases} a_i &amp;&lt;: \sigma U_i &amp; \quad (i = 1, \ldots , n) \\ \sigma L_i &amp;&lt;: a_i &amp; \quad (i = 1, \ldots , n) \end{cases}

where σ\sigma is the substitution [a1:=a1,,an:=an][a_1&#x27; := a_1 , \ldots , a_n&#x27; :=a_n].

The set C0\mathcal{C}_0 is then augmented by further subtype constraints. There are two cases.

Case 1

If there exists a substitution σ\sigma over the type variables ai,,ana_i , \ldots , a_n such that σT\sigma T conforms to pt\mathit{pt}, one determines the weakest subtype constraints C1\mathcal{C}_1 over the type variables a1,,ana_1, \ldots , a_n such that C0C1\mathcal{C}_0 \wedge \mathcal{C}_1 implies that TT conforms to pt\mathit{pt}.

Case 2

Otherwise, if TT can not be made to conform to pt\mathit{pt} by instantiating its type variables, one determines all type variables in pt\mathit{pt} which are defined as type parameters of a method enclosing the pattern. Let the set of such type parameters be b1,,bmb_1 , \ldots , b_m. Let C0\mathcal{C}_0&#x27; be the subtype constraints reflecting the bounds of the type variables bib_i. If TT denotes an instance type of a final class, let C2\mathcal{C}_2 be the weakest set of subtype constraints over the type variables a1,,ana_1 , \ldots , a_n and b1,,bmb_1 , \ldots , b_m such that C0C0C2\mathcal{C}_0 \wedge \mathcal{C}_0&#x27; \wedge \mathcal{C}_2 implies that TT conforms to pt\mathit{pt}. If TT does not denote an instance type of a final class, let C2\mathcal{C}_2 be the weakest set of subtype constraints over the type variables a1,,ana_1 , \ldots , a_n and b1,,bmb_1 , \ldots , b_m such that C0C0C2\mathcal{C}_0 \wedge \mathcal{C}_0&#x27; \wedge \mathcal{C}_2 implies that it is possible to construct a type TT&#x27; which conforms to both TT and pt\mathit{pt}. It is a static error if there is no satisfiable set of constraints C2\mathcal{C}_2 with this property.

The final step consists in choosing type bounds for the type variables which imply the established constraint system. The process is different for the two cases above.

Case 1

We take ai&gt;:Li&lt;:Uia_i &gt;: L_i &lt;: U_i where each LiL_i is minimal and each UiU_i is maximal wrt &lt;:&lt;: such that ai&gt;:Li&lt;:Uia_i &gt;: L_i &lt;: U_i for i=1,,ni = 1, \ldots, n implies C0C1\mathcal{C}_0 \wedge \mathcal{C}_1.

Case 2

We take ai&gt;:Li&lt;:Uia_i &gt;: L_i &lt;: U_i and bi&gt;:Li&lt;:Uib_i &gt;: L_i&#x27; &lt;: U_i&#x27; where each LiL_i and LjL_j&#x27; is minimal and each UiU_i and UjU_j&#x27; is maximal such that ai&gt;:Li&lt;:Uia_i &gt;: L_i &lt;: U_i for i=1,,ni = 1 , \ldots , n and bj&gt;:Lj&lt;:Ujb_j &gt;: L_j&#x27; &lt;: U_j&#x27; for j=1,,mj = 1 , \ldots , m implies C0C0C2\mathcal{C}_0 \wedge \mathcal{C}_0&#x27; \wedge \mathcal{C}_2.

In both cases, local type inference is permitted to limit the complexity of inferred bounds. Minimality and maximality of types have to be understood relative to the set of types of acceptable complexity.

Type parameter inference for constructor patterns

Assume a constructor pattern C(p1,,pn)C(p_1 , \ldots , p_n) where class CC has type parameters a1,,ana_1 , \ldots , a_n. These type parameters are inferred in the same way as for the typed pattern (_: C[a1,,an]C[a_1 , \ldots , a_n]).

Example

Consider the program fragment:

val x: Any
x match {
  case y: List[a] => ...
}

Here, the type pattern List[a] is matched against the expected type Any. The pattern binds the type variable a. Since List[a] conforms to Any for every type argument, there are no constraints on a. Hence, a is introduced as an abstract type with no bounds. The scope of a is right-hand side of its case clause.

On the other hand, if x is declared as

val x: List[List[String]],

this generates the constraint List[a] <: List[List[String]], which simplifies to a <: List[String], because List is covariant. Hence, a is introduced with upper bound List[String].

Example

Consider the program fragment:

val x: Any
x match {
  case y: List[String] => ...
}

Scala does not maintain information about type arguments at run-time, so there is no way to check that x is a list of strings. Instead, the Scala compiler will erase the pattern to List[_]; that is, it will only test whether the top-level runtime-class of the value x conforms to List, and the pattern match will succeed if it does. This might lead to a class cast exception later on, in the case where the list x contains elements other than strings. The Scala compiler will flag this potential loss of type-safety with an "unchecked" warning message.

Example

Consider the program fragment

class Term[A]
class Number(val n: Int) extends Term[Int]
def f[B](t: Term[B]): B = t match {
  case y: Number => y.n
}

The expected type of the pattern y: Number is Term[B]. The type Number does not conform to Term[B]; hence Case 2 of the rules above applies. This means that B is treated as another type variable for which subtype constraints are inferred. In our case the applicable constraint is Number <: Term[B], which entails B = Int. Hence, B is treated in the case clause as an abstract type with lower and upper bound Int. Therefore, the right hand side of the case clause, y.n, of type Int, is found to conform to the function's declared result type, Number.

Pattern Matching Expressions

  Expr            ::=  PostfixExpr ‘match’ ‘{’ CaseClauses ‘}’
  CaseClauses     ::=  CaseClause {CaseClause}
  CaseClause      ::=  ‘case’ Pattern [Guard] ‘=>’ Block

A pattern matching expression

e match { case p1p_1 => b1b_1 \ldots case pnp_n => bnb_n }

consists of a selector expression ee and a number n&gt;0n &gt; 0 of cases. Each case consists of a (possibly guarded) pattern pip_i and a block bib_i. Each pip_i might be complemented by a guard if ee where ee is a boolean expression. The scope of the pattern variables in pip_i comprises the pattern's guard and the corresponding block bib_i.

Let TT be the type of the selector expression ee and let a1,,ama_1 , \ldots , a_m be the type parameters of all methods enclosing the pattern matching expression. For every aia_i, let LiL_i be its lower bound and UiU_i be its higher bound. Every pattern pp1,,,pnp \in {p_1, , \ldots , p_n} can be typed in two ways. First, it is attempted to type pp with TT as its expected type. If this fails, pp is instead typed with a modified expected type TT&#x27; which results from TT by replacing every occurrence of a type parameter aia_i by undefined. If this second step fails also, a compile-time error results. If the second step succeeds, let TpT_p be the type of pattern pp seen as an expression. One then determines minimal bounds L11,,LmL_11 , \ldots , L_m&#x27; and maximal bounds U1,,UmU_1&#x27; , \ldots , U_m&#x27; such that for all ii, Li&lt;:LiL_i &lt;: L_i&#x27; and Ui&lt;:UiU_i&#x27; &lt;: U_i and the following constraint system is satisfied:

L1&lt;:a1&lt;:U1&ThickSpace;&ThickSpace;&ThickSpace;&ThickSpace;Lm&lt;:am&lt;:Um  Tp&lt;:T L_1 &lt;: a_1 &lt;: U_1\;\wedge\;\ldots\;\wedge\;L_m &lt;: a_m &lt;: U_m \ \Rightarrow\ T_p &lt;: T

If no such bounds can be found, a compile time error results. If such bounds are found, the pattern matching clause starting with pp is then typed under the assumption that each aia_i has lower bound LiL_i&#x27; instead of LiL_i and has upper bound UiU_i&#x27; instead of UiU_i.

The expected type of every block bib_i is the expected type of the whole pattern matching expression. The type of the pattern matching expression is then the weak least upper bound of the types of all blocks bib_i.

When applying a pattern matching expression to a selector value, patterns are tried in sequence until one is found which matches the selector value. Say this case is case pibip_i \Rightarrow b_i. The result of the whole expression is the result of evaluating bib_i, where all pattern variables of pip_i are bound to the corresponding parts of the selector value. If no matching pattern is found, a scala.MatchError exception is thrown.

The pattern in a case may also be followed by a guard suffix if e with a boolean expression ee. The guard expression is evaluated if the preceding pattern in the case matches. If the guard expression evaluates to true, the pattern match succeeds as normal. If the guard expression evaluates to false, the pattern in the case is considered not to match and the search for a matching pattern continues.

In the interest of efficiency the evaluation of a pattern matching expression may try patterns in some other order than textual sequence. This might affect evaluation through side effects in guards. However, it is guaranteed that a guard expression is evaluated only if the pattern it guards matches.

If the selector of a pattern match is an instance of a sealed class, the compilation of pattern matching can emit warnings which diagnose that a given set of patterns is not exhaustive, i.e. that there is a possibility of a MatchError being raised at run-time.

Example

Consider the following definitions of arithmetic terms:

abstract class Term[T]
case class Lit(x: Int) extends Term[Int]
case class Succ(t: Term[Int]) extends Term[Int]
case class IsZero(t: Term[Int]) extends Term[Boolean]
case class If[T](c: Term[Boolean],
                 t1: Term[T],
                 t2: Term[T]) extends Term[T]

There are terms to represent numeric literals, incrementation, a zero test, and a conditional. Every term carries as a type parameter the type of the expression it represents (either Int or Boolean).

A type-safe evaluator for such terms can be written as follows.

def eval[T](t: Term[T]): T = t match {
  case Lit(n)        => n
  case Succ(u)       => eval(u) + 1
  case IsZero(u)     => eval(u) == 0
  case If(c, u1, u2) => eval(if (eval(c)) u1 else u2)
}

Note that the evaluator makes crucial use of the fact that type parameters of enclosing methods can acquire new bounds through pattern matching.

For instance, the type of the pattern in the second case, Succ(u), is Int. It conforms to the selector type T only if we assume an upper and lower bound of Int for T. Under the assumption Int <: T <: Int we can also verify that the type right hand side of the second case, Int conforms to its expected type, T.

Pattern Matching Anonymous Functions

  BlockExpr ::= ‘{’ CaseClauses ‘}’

An anonymous function can be defined by a sequence of cases

{ case p1p_1 => b1b_1 \ldots case pnp_n => bnb_n }

which appear as an expression without a prior match. The expected type of such an expression must in part be defined. It must be either scala.Functionkk[S1,,SkS_1 , \ldots , S_k, RR] for some k&gt;0k &gt; 0, or scala.PartialFunction[S1S_1, RR], where the argument type(s) S1,,SkS_1 , \ldots , S_k must be fully determined, but the result type RR may be undetermined.

If the expected type is SAM-convertible to scala.Functionkk[S1,,SkS_1 , \ldots , S_k, RR], the expression is taken to be equivalent to the anonymous function:

(x1:S1,,xk:Skx_1: S_1 , \ldots , x_k: S_k) => (x1,,xkx_1 , \ldots , x_k) match {
  case p1p_1 => b1b_1 \ldots case pnp_n => bnb_n
}

Here, each xix_i is a fresh name. As was shown here, this anonymous function is in turn equivalent to the following instance creation expression, where TT is the weak least upper bound of the types of all bib_i.

new scala.Functionkk[S1,,SkS_1 , \ldots , S_k, TT] {
  def apply(x1:S1,,xk:Skx_1: S_1 , \ldots , x_k: S_k): TT = (x1,,xkx_1 , \ldots , x_k) match {
    case p1p_1 => b1b_1 \ldots case pnp_n => bnb_n
  }
}

If the expected type is scala.PartialFunction[SS, RR], the expression is taken to be equivalent to the following instance creation expression:

new scala.PartialFunction[SS, TT] {
  def apply(xx: SS): TT = x match {
    case p1p_1 => b1b_1 \ldots case pnp_n => bnb_n
  }
  def isDefinedAt(xx: SS): Boolean = {
    case p1p_1 => true \ldots case pnp_n => true
    case _ => false
  }
}

Here, xx is a fresh name and TT is the weak least upper bound of the types of all bib_i. The final default case in the isDefinedAt method is omitted if one of the patterns p1,,pnp_1 , \ldots , p_n is already a variable or wildcard pattern.

Example

Here's an example which uses foldLeft to compute the scalar product of two vectors:

def scalarProduct(xs: Array[Double], ys: Array[Double]) =
  (xs zip ys).foldLeft(0.0) {
    case (a, (b, c)) => a + b * c
  }

The case clauses in this code are equivalent to the following anonymous function:

(x, y) => (x, y) match {
  case (a, (b, c)) => a + b * c
}