Expressions

Expr         ::=  (Bindings | id | ‘_’) ‘=>’ Expr
               |  Expr1
Expr1        ::=  ‘if’ ‘(’ Expr ‘)’ {nl} Expr [[semi] ‘else’ Expr]
               |  ‘while’ ‘(’ Expr ‘)’ {nl} Expr
               |  ‘try’ Expr [‘catch’ Expr] [‘finally’ Expr]
               |  ‘do’ Expr [semi] ‘while’ ‘(’ Expr ‘)’
               |  ‘for’ (‘(’ Enumerators ‘)’ | ‘{’ Enumerators ‘}’) {nl} [‘yield’] Expr
               |  ‘throw’ Expr
               |  ‘return’ [Expr]
               |  [SimpleExpr ‘.’] id ‘=’ Expr
               |  SimpleExpr1 ArgumentExprs ‘=’ Expr
               |  PostfixExpr
               |  PostfixExpr Ascription
               |  PostfixExpr ‘match’ ‘{’ CaseClauses ‘}’
PostfixExpr  ::=  InfixExpr [id [nl]]
InfixExpr    ::=  PrefixExpr
               |  InfixExpr id [nl] InfixExpr
PrefixExpr   ::=  [‘-’ | ‘+’ | ‘~’ | ‘!’] SimpleExpr
SimpleExpr   ::=  ‘new’ (ClassTemplate | TemplateBody)
               |  BlockExpr
               |  SimpleExpr1 [‘_’]
SimpleExpr1  ::=  Literal
               |  Path
               |  ‘_’
               |  ‘(’ [Exprs] ‘)’
               |  SimpleExpr ‘.’ id
               |  SimpleExpr TypeArgs
               |  SimpleExpr1 ArgumentExprs
               |  XmlExpr
Exprs        ::=  Expr {‘,’ Expr}
BlockExpr    ::=  ‘{’ CaseClauses ‘}’
               |  ‘{’ Block ‘}’
Block        ::=  BlockStat {semi BlockStat} [ResultExpr]
ResultExpr   ::=  Expr1
               |  (Bindings | ([‘implicit’] id | ‘_’) ‘:’ CompoundType) ‘=>’ Block
Ascription   ::=  ‘:’ InfixType
               |  ‘:’ Annotation {Annotation}
               |  ‘:’ ‘_’ ‘*’

Expressions are composed of operators and operands. Expression forms are discussed subsequently in decreasing order of precedence.

Expression Typing

The typing of expressions is often relative to some expected type (which might be undefined). When we write "expression ee is expected to conform to type TT", we mean:

  1. the expected type of ee is TT, and
  2. the type of expression ee must conform to TT.

The following skolemization rule is applied universally for every expression: If the type of an expression would be an existential type TT, then the type of the expression is assumed instead to be a skolemization of TT.

Skolemization is reversed by type packing. Assume an expression ee of type TT and let t1[tps1]>:L1<:U1,,tn[tpsn]>:Ln<:Unt_1[\mathit{tps}_1] >: L_1 <: U_1 , \ldots , t_n[\mathit{tps}_n] >: L_n <: U_n be all the type variables created by skolemization of some part of ee which are free in TT. Then the packed type of ee is

TT forSome { type t1[tps_1]>:L1<:U1t_1[\mathit{tps}\_1] >: L_1 <: U_1; \ldots; type tn[tps_n]>:Ln<:Unt_n[\mathit{tps}\_n] >: L_n <: U_n }.

Literals

SimpleExpr    ::=  Literal

Typing of literals is described along with their lexical syntax; their evaluation is immediate.

The Null Value

The null value is of type scala.Null, and thus conforms to every reference type. It denotes a reference value which refers to a special null object. This object implements methods in class scala.AnyRef as follows:

A reference to any other member of the "null" object causes a NullPointerException to be thrown.

Designators

SimpleExpr  ::=  Path
              |  SimpleExpr ‘.’ id

A designator refers to a named term. It can be a simple name or a selection.

A simple name xx refers to a value as specified here. If xx is bound by a definition or declaration in an enclosing class or object CC, it is taken to be equivalent to the selection CC.this.xx where CC is taken to refer to the class containing xx even if the type name CC is shadowed at the occurrence of xx.

If rr is a stable identifier of type TT, the selection r.xr.x refers statically to a term member mm of rr that is identified in TT by the name xx.

For other expressions ee, e.xe.x is typed as if it was { val yy = ee; yy.xx }, for some fresh name yy.

The expected type of a designator's prefix is always undefined. The type of a designator is the type TT of the entity it refers to, with the following exception: The type of a path pp which occurs in a context where a stable type is required is the singleton type pp.type.

The contexts where a stable type is required are those that satisfy one of the following conditions:

  1. The path pp occurs as the prefix of a selection and it does not designate a constant, or
  2. The expected type pt\mathit{pt} is a stable type, or
  3. The expected type pt\mathit{pt} is an abstract type with a stable type as lower bound, and the type TT of the entity referred to by pp does not conform to pt\mathit{pt}, or
  4. The path pp designates a module.

The selection e.xe.x is evaluated by first evaluating the qualifier expression ee, which yields an object rr, say. The selection's result is then the member of rr that is either defined by mm or defined by a definition overriding mm.

This and Super

SimpleExpr  ::=  [id ‘.’] ‘this’
              |  [id ‘.’] ‘super’ [ClassQualifier] ‘.’ id

The expression this can appear in the statement part of a template or compound type. It stands for the object being defined by the innermost template or compound type enclosing the reference. If this is a compound type, the type of this is that compound type. If it is a template of a class or object definition with simple name CC, the type of this is the same as the type of CC.this.

The expression CC.this is legal in the statement part of an enclosing class or object definition with simple name CC. It stands for the object being defined by the innermost such definition. If the expression's expected type is a stable type, or CC.this occurs as the prefix of a selection, its type is CC.this.type, otherwise it is the self type of class CC.

A reference super.mm refers statically to a method or type mm in the least proper supertype of the innermost template containing the reference. It evaluates to the member mm' in the actual supertype of that template which is equal to mm or which overrides mm. The statically referenced member mm must be a type or a method.

If it is a method, it must be concrete, or the template containing the reference must have a member mm' which overrides mm and which is labeled abstract override.

A reference CC.super.mm refers statically to a method or type mm in the least proper supertype of the innermost enclosing class or object definition named CC which encloses the reference. It evaluates to the member mm' in the actual supertype of that class or object which is equal to mm or which overrides mm. The statically referenced member mm must be a type or a method. If the statically referenced member mm is a method, it must be concrete, or the innermost enclosing class or object definition named CC must have a member mm' which overrides mm and which is labeled abstract override.

The super prefix may be followed by a trait qualifier [T T\,], as in CC.super[T T\,].xx. This is called a static super reference. In this case, the reference is to the type or method of xx in the parent trait of CC whose simple name is TT. That member must be uniquely defined. If it is a method, it must be concrete.

Example

Consider the following class definitions

class Root { def x = "Root" }
class A extends Root { override def x = "A" ; def superA = super.x }
trait B extends Root { override def x = "B" ; def superB = super.x }
class C extends Root with B {
  override def x = "C" ; def superC = super.x
}
class D extends A with B {
  override def x = "D" ; def superD = super.x
}

The linearization of class C is {C, B, Root} and the linearization of class D is {D, B, A, Root}. Then we have:

(new A).superA == "Root"

(new C).superB == "Root"
(new C).superC == "B"

(new D).superA == "Root"
(new D).superB == "A"
(new D).superD == "B"

Note that the superB method returns different results depending on whether B is mixed in with class Root or A.

Function Applications

SimpleExpr    ::=  SimpleExpr1 ArgumentExprs
ArgumentExprs ::=  ‘(’ [Exprs] ‘)’
                |  ‘(’ ‘using’ Exprs ‘)’
                |  ‘(’ [Exprs ‘,’] PostfixExpr ‘:’ ‘_’ ‘*’ ‘)’
                |  [nl] BlockExpr
Exprs         ::=  Expr {‘,’ Expr}

An application f(e1,,em)f(e_1 , \ldots , e_m) applies the function ff to the argument expressions e1,,eme_1, \ldots , e_m. For this expression to be well-typed, the function must be applicable to its arguments, which is defined next by case analysis on ff's type.

If ff has a method type (p1p_1:T1,,pnT_1 , \ldots , p_n:TnT_n)UU, each argument expression eie_i is typed with the corresponding parameter type TiT_i as expected type. Let SiS_i be the type of argument eie_i (i=1,,m)(i = 1 , \ldots , m). The method ff must be applicable to its arguments e1,,ene_1, \ldots , e_n of types S1,,SnS_1 , \ldots , S_n. We say that an argument expression eie_i is a named argument if it has the form xi=eix_i=e'_i and xix_i is one of the parameter names p1,,pnp_1, \ldots, p_n.

Once the types SiS_i have been determined, the method ff of the above method type is said to be applicable if all of the following conditions hold:

If ff is a polymorphic method, local type inference is used to instantiate ff's type parameters. The polymorphic method is applicable if type inference can determine type arguments so that the instantiated method is applicable.

If ff has some value type, the application is taken to be equivalent to ff.apply(e1,,eme_1 , \ldots , e_m), i.e. the application of an apply method defined by ff. The value ff is applicable to the given arguments if ff.apply is applicable.

The application ff(e1,,ene_1 , \ldots , e_n) evaluates ff and then each argument e1,,ene_1 , \ldots , e_n from left to right, except for arguments that correspond to a by-name parameter (see below). Each argument expression is converted to the type of its corresponding formal parameter. After that, the application is rewritten to the function's right hand side, with actual arguments substituted for formal parameters. The result of evaluating the rewritten right-hand side is finally converted to the function's declared result type, if one is given.

The case of a formal parameter with a parameterless method type => TT is treated specially. In this case, the corresponding actual argument expression ee is not evaluated before the application. Instead, every use of the formal parameter on the right-hand side of the rewrite rule entails a re-evaluation of ee. In other words, the evaluation order for =>-parameters is call-by-name whereas the evaluation order for normal parameters is call-by-value. Furthermore, it is required that ee's packed type conforms to the parameter type TT. The behavior of by-name parameters is preserved if the application is transformed into a block due to named or default arguments. In this case, the local value for that parameter has the form val yiy_i = () => ee and the argument passed to the function is yiy_i().

The last argument in an application may be marked as a sequence argument, e.g. ee: _*. Such an argument must correspond to a repeated parameter of type SS* and it must be the only argument matching this parameter (i.e. the number of formal parameters and actual arguments must be the same). Furthermore, the type of ee must conform to scala.Seq[TT], for some type TT which conforms to SS. In this case, the argument list is transformed by replacing the sequence ee with its elements. When the application uses named arguments, the vararg parameter has to be specified exactly once.

If only a single argument is supplied, it may be supplied as a block expression and parentheses can be omitted, in the form ff { block }. This is valid when f has a single formal parameter or when all other formal parameters have default values.

A function application usually allocates a new frame on the program's run-time stack. However, if a local method or a final method calls itself as its last action, the call is executed using the stack-frame of the caller.

Example

Assume the following method which computes the sum of a variable number of arguments:

def sum(xs: Int*) = xs.foldLeft(0)((x, y) => x + y)

Then

sum(1, 2, 3, 4)
sum(List(1, 2, 3, 4): _*)

both yield 10 as result. On the other hand,

sum(List(1, 2, 3, 4))

would not typecheck.

An argument list may begin with the soft keyword using to facilitate cross-compilation with Scala 3. The keyword is ignored.

Named and Default Arguments

If an application is to use named arguments p=ep = e or default arguments, the following conditions must hold.

If the application uses named or default arguments the following transformation is applied to convert it into an application without named or default arguments.

If the method ff has the form p.mp.m[targs\mathit{targs}] it is transformed into the block

{ val q = pp
  q.mm[targs\mathit{targs}]
}

If the method ff is itself an application expression the transformation is applied recursively on ff. The result of transforming ff is a block of the form

{ val q = pp
  val x1x_1 = expr1_1
  \ldots
  val xkx_k = exprk_k
  q.mm[targs\mathit{targs}](args1\mathit{args}_1),,, \ldots ,(argsl\mathit{args}_l)
}

where every argument in (args1),,(argsl)(\mathit{args}_1) , \ldots , (\mathit{args}_l) is a reference to one of the values x1,,xkx_1 , \ldots , x_k. To integrate the current application into the block, first a value definition using a fresh name yiy_i is created for every argument in e1,,eme_1 , \ldots , e_m, which is initialised to eie_i for positional arguments and to eie'_i for named arguments of the form xi=eix_i=e'_i. Then, for every parameter which is not specified by the argument list, a value definition using a fresh name ziz_i is created, which is initialized using the method computing the default argument of this parameter.

Let args\mathit{args} be a permutation of the generated names yiy_i and ziz_i such such that the position of each name matches the position of its corresponding parameter in the method type (p1:T1,,pn:Tnp_1:T_1 , \ldots , p_n:T_n)UU. The final result of the transformation is a block of the form

{ val q = pp
  val x1x_1 = expr1_1
  \ldots
  val xlx_l = exprk_k
  val y1y_1 = e1e_1
  \ldots
  val ymy_m = eme_m
  val z1z_1 = q.m$default$i[targs](args1),,(argsl)q.m\$default\$i[\mathit{targs}](\mathit{args}_1), \ldots ,(\mathit{args}_l)
  \ldots
  val zdz_d = q.m$default$j[targs](args1),,(argsl)q.m\$default\$j[\mathit{targs}](\mathit{args}_1), \ldots ,(\mathit{args}_l)
  q.mm[targs\mathit{targs}](args1\mathit{args}_1),,, \ldots ,(argsl\mathit{args}_l)(args\mathit{args})
}

Signature Polymorphic Methods

For invocations of signature polymorphic methods of the target platform ff(e1,,eme_1 , \ldots , e_m), the invoked method has a different method type (p1p_1:T1,,pnT_1 , \ldots , p_n:TnT_n)UU at each call site. The parameter types T,,TnT_ , \ldots , T_n are the types of the argument expressions e1,,eme_1 , \ldots , e_m. If the declared return type RR of the signature polymorphic method is any type other than scala.AnyRef, then the return type UU is RR. Otherwise, UU is the expected type at the call site. If the expected type is undefined then UU is scala.AnyRef. The parameter names p1,,pnp_1 , \ldots , p_n are fresh.

Note

On the Java platform version 11 and later, a method is signature polymorphic if it is native, a member of java.lang.invoke.MethodHandle or java.lang.invoke.VarHandle, and has a single repeated parameter of type java.lang.Object*. (These requirements also work for Java 8, which had fewer such methods.)

Method Values

SimpleExpr    ::=  SimpleExpr1 ‘_’

The expression ee _ is well-formed if ee is of method type or if ee is a call-by-name parameter. If ee is a method with parameters, ee _ represents ee converted to a function type by eta expansion. If ee is a parameterless method or call-by-name parameter of type => TT, ee _ represents the function of type () => TT, which evaluates ee when it is applied to the empty parameter list ().

Example

The method values in the left column are each equivalent to the eta-expanded expressions on the right.

placeholder syntax eta-expansion
math.sin _ x => math.sin(x)
math.pow _ (x1, x2) => math.pow(x1, x2)
val vs = 1 to 9; vs.fold _ (z) => (op) => vs.fold(z)(op)
(1 to 9).fold(z)_ { val eta1 = 1 to 9; val eta2 = z; op => eta1.fold(eta2)(op) }
Some(1).fold(??? : Int)_ { val eta1 = Some(1); val eta2 = () => ???; op => eta1.fold(eta2())(op) }

Note that a space is necessary between a method name and the trailing underscore because otherwise the underscore would be considered part of the name.

Type Applications

SimpleExpr    ::=  SimpleExpr TypeArgs

A type application ee[T1,,TnT_1 , \ldots , T_n] instantiates a polymorphic value ee of type [a1a_1 >: L1L_1 <: U1,,anU_1, \ldots , a_n >: LnL_n <: UnU_n]SS with argument types T1,,TnT_1 , \ldots , T_n. Every argument type TiT_i must obey the corresponding bounds LiL_i and UiU_i. That is, for each i=1,,ni = 1 , \ldots , n, we must have σLi&lt;:Ti&lt;:σUi\sigma L_i &lt;: T_i &lt;: \sigma U_i, where σ\sigma is the substitution [a1:=T1,,an:=Tn][a_1 := T_1 , \ldots , a_n := T_n]. The type of the application is σS\sigma S.

If the function part ee is of some value type, the type application is taken to be equivalent to ee.apply[T1,,T_1 , \ldots , Tn_n], i.e. the application of an apply method defined by ee.

Type applications can be omitted if local type inference can infer best type parameters for a polymorphic method from the types of the actual method arguments and the expected result type.

Tuples

SimpleExpr   ::=  ‘(’ [Exprs] ‘)’

A tuple expression (e1,,ene_1 , \ldots , e_n) is an alias for the class instance creation scala.Tuplenn(e1,,ene_1 , \ldots , e_n), where n2n \geq 2. The empty tuple () is the unique value of type scala.Unit.

Instance Creation Expressions

SimpleExpr     ::=  ‘new’ (ClassTemplate | TemplateBody)

A simple instance creation expression is of the form new cc where cc is a constructor invocation. Let TT be the type of cc. Then TT must denote a (a type instance of) a non-abstract subclass of scala.AnyRef. Furthermore, the concrete self type of the expression must conform to the self type of the class denoted by TT. The concrete self type is normally TT, except if the expression new cc appears as the right hand side of a value definition

val xx: SS = new cc

(where the type annotation : SS may be missing). In the latter case, the concrete self type of the expression is the compound type TT with xx.type.

The expression is evaluated by creating a fresh object of type TT which is initialized by evaluating cc. The type of the expression is TT.

A general instance creation expression is of the form new tt for some class template tt. Such an expression is equivalent to the block

{ class aa extends tt; new aa }

where aa is a fresh name of an anonymous class which is inaccessible to user programs.

There is also a shorthand form for creating values of structural types: If {DD} is a class body, then new {DD} is equivalent to the general instance creation expression new AnyRef{DD}.

Example

Consider the following structural instance creation expression:

new { def getName() = "aaron" }

This is a shorthand for the general instance creation expression

new AnyRef{ def getName() = "aaron" }

The latter is in turn a shorthand for the block

{ class anon$X extends AnyRef{ def getName() = "aaron" }; new anon$X }

where anon$X is some freshly created name.

Blocks

BlockExpr  ::=  ‘{’ CaseClauses ‘}’
             |  ‘{’ Block ‘}’
Block      ::=  BlockStat {semi BlockStat} [ResultExpr]

A block expression {s1s_1; \ldots; sns_n; e&ThinSpace;e\,} is constructed from a sequence of block statements s1,,sns_1 , \ldots , s_n and a final expression ee. The statement sequence may not contain two definitions or declarations that bind the same name in the same namespace. The final expression can be omitted, in which case the unit value () is assumed.

The expected type of the final expression ee is the expected type of the block. The expected type of all preceding statements is undefined.

The type of a block s1s_1; \ldots; sns_n; ee is TT forSome {&ThinSpace;Q&ThinSpace;\,Q\,}, where TT is the type of ee and QQ contains existential clauses for every value or type name which is free in TT and which is defined locally in one of the statements s1,,sns_1 , \ldots , s_n. We say the existential clause binds the occurrence of the value or type name. Specifically,

Evaluation of the block entails evaluation of its statement sequence, followed by an evaluation of the final expression ee, which defines the result of the block.

A block expression {c1c_1; \ldots; cnc_n} where s1,,sns_1 , \ldots , s_n are case clauses forms a pattern matching anonymous function.

Example

Assuming a class Ref[T](x: T), the block

{ class C extends B {\ldots} ; new Ref(new C) }

has the type Ref[_1] forSome { type _1 <: B }. The block

{ class C extends B {\ldots} ; new C }

simply has type B, because with the rules here the existentially quantified type _1 forSome { type _1 <: B } can be simplified to B.

Prefix, Infix, and Postfix Operations

PostfixExpr     ::=  InfixExpr [id [nl]]
InfixExpr       ::=  PrefixExpr
                  |  InfixExpr id [nl] InfixExpr
PrefixExpr      ::=  [‘-’ | ‘+’ | ‘!’ | ‘~’] SimpleExpr

Expressions can be constructed from operands and operators.

Prefix Operations

A prefix operation op;e\mathit{op};e consists of a prefix operator op\mathit{op}, which must be one of the identifiers ‘+’, ‘-’, ‘!’ or ‘~’, which must not be enclosed in backquotes. The expression op;e\mathit{op};e is equivalent to the postfix method application e.unary_op\mathit{op}.

Prefix operators are different from normal method applications in that their operand expression need not be atomic. For instance, the input sequence -sin(x) is read as -(sin(x)), whereas the method application negate sin(x) would be parsed as the application of the infix operator sin to the operands negate and (x).

Postfix Operations

A postfix operator can be an arbitrary identifier. The postfix operation e;ope;\mathit{op} is interpreted as e.ope.\mathit{op}.

Infix Operations

An infix operator can be an arbitrary identifier. Infix operators have precedence and associativity defined as follows:

The precedence of an infix operator is determined by the operator's first character. Characters are listed below in increasing order of precedence, with characters on the same line having the same precedence.

(all letters, as defined in [chapter 1](01-lexical-syntax.html), including `_` and `$`)
|
^
&
= !
< >
:
+ -
* / %
(other operator characters, as defined in [chapter 1](01-lexical-syntax.html), including Unicode categories `Sm` and `So`)

That is, operators starting with a letter have lowest precedence, followed by operators starting with ‘|’, etc.

There's one exception to this rule, which concerns assignment operators. The precedence of an assignment operator is the same as the one of simple assignment (=). That is, it is lower than the precedence of any other operator.

The associativity of an operator is determined by the operator's last character. Operators ending in a colon ‘:’ are right-associative. All other operators are left-associative.

Precedence and associativity of operators determine the grouping of parts of an expression as follows.

The right-hand operand of a left-associative operator may consist of several arguments enclosed in parentheses, e.g. e;op;(e1,,en)e;\mathit{op};(e_1,\ldots,e_n). This expression is then interpreted as e.op(e1,,en)e.\mathit{op}(e_1,\ldots,e_n).

A left-associative binary operation e1;op;e2e_1;\mathit{op};e_2 is interpreted as e1.op(e2)e_1.\mathit{op}(e_2). If op\mathit{op} is right-associative and its parameter is passed by name, the same operation is interpreted as e2.op(e1)e_2.\mathit{op}(e_1). If op\mathit{op} is right-associative and its parameter is passed by value, it is interpreted as { val xx=e1e_1; e2e_2.op\mathit{op}(x&ThinSpace;x\,) }, where xx is a fresh name.

Assignment Operators

An assignment operator is an operator symbol (syntax category op in Identifiers) that ends in an equals character “=”, with the following exceptions:

  1. the operator also starts with an equals character, or
  2. the operator is one of (<=), (>=), (!=).

Assignment operators are treated specially in that they can be expanded to assignments if no other interpretation is valid.

Let's consider an assignment operator such as += in an infix operation ll += rr, where ll, rr are expressions. This operation can be re-interpreted as an operation which corresponds to the assignment

ll = ll + rr

except that the operation's left-hand-side ll is evaluated only once.

The re-interpretation occurs if the following two conditions are fulfilled.

  1. The left-hand-side ll does not have a member named +=, and also cannot be converted by an implicit conversion to a value with a member named +=.
  2. The assignment ll = ll + rr is type-correct. In particular this implies that ll refers to a variable or object that can be assigned to, and that is convertible to a value with a member named +.

Typed Expressions

Expr1              ::=  PostfixExpr ‘:’ CompoundType

The typed expression e:Te: T has type TT. The type of expression ee is expected to conform to TT. The result of the expression is the value of ee converted to type TT.

Example

Here are examples of well-typed and ill-typed expressions.

1: Int               // legal, of type Int
1: Long              // legal, of type Long
// 1: string         // ***** illegal

Annotated Expressions

Expr1              ::=  PostfixExpr ‘:’ Annotation {Annotation}

An annotated expression ee: @a1a_1 \ldots @ana_n attaches annotations a1,,ana_1 , \ldots , a_n to the expression ee.

Assignments

Expr1        ::=  [SimpleExpr ‘.’] id ‘=’ Expr
               |  PrefixOperator SimpleExpr ‘=’ Expr
               |  SimpleExpr1 ArgumentExprs ‘=’ Expr

The interpretation of an assignment to a simple variable xx = ee depends on the definition of xx. If xx denotes a mutable variable, then the assignment changes the current value of xx to be the result of evaluating the expression ee. The type of ee is expected to conform to the type of xx. If xx is a parameterless method defined in some template, and the same template contains a setter method xx_= as member, then the assignment xx = ee is interpreted as the invocation xx_=(e&ThinSpace;e\,) of that setter method. Analogously, an assignment f.xf.x = ee to a parameterless method xx is interpreted as the invocation f.xf.x_=(e&ThinSpace;e\,). If xx is an application of a unary operator, then the expression is interpreted as though it were written as the explicit application xx.unary_op\mathit{op}, namely, as xx.unary_op\mathit{op}_=(e&ThinSpace;e\,).

An assignment ff(args&ThinSpace;\mathit{args}\,) = ee with a method application to the left of the ‘=’ operator is interpreted as f.f.update(args\mathit{args}, e&ThinSpace;e\,), i.e. the invocation of an update method defined by ff.

Example

Here are some assignment expressions and their equivalent expansions.

assignment expansion
x.f = e x.f_=(e)
x.f() = e x.f.update(e)
x.f(i) = e x.f.update(i, e)
x.f(i, j) = e x.f.update(i, j, e)
Example Imperative Matrix Multiplication

Here is the usual imperative code for matrix multiplication.

def matmul(xss: Array[Array[Double]], yss: Array[Array[Double]]) = {
  val zss: Array[Array[Double]] = new Array(xss.length, yss(0).length)
  var i = 0
  while (i < xss.length) {
    var j = 0
    while (j < yss(0).length) {
      var acc = 0.0
      var k = 0
      while (k < yss.length) {
        acc = acc + xss(i)(k) * yss(k)(j)
        k += 1
      }
      zss(i)(j) = acc
      j += 1
    }
    i += 1
  }
  zss
}

Desugaring the array accesses and assignments yields the following expanded version:

def matmul(xss: Array[Array[Double]], yss: Array[Array[Double]]) = {
  val zss: Array[Array[Double]] = new Array(xss.length, yss.apply(0).length)
  var i = 0
  while (i < xss.length) {
    var j = 0
    while (j < yss.apply(0).length) {
      var acc = 0.0
      var k = 0
      while (k < yss.length) {
        acc = acc + xss.apply(i).apply(k) * yss.apply(k).apply(j)
        k += 1
      }
      zss.apply(i).update(j, acc)
      j += 1
    }
    i += 1
  }
  zss
}

Conditional Expressions

Expr1          ::=  ‘if’ ‘(’ Expr ‘)’ {nl} Expr [[semi] ‘else’ Expr]

The conditional expression if (e1e_1) e2e_2 else e3e_3 chooses one of the values of e2e_2 and e3e_3, depending on the value of e1e_1. The condition e1e_1 is expected to conform to type Boolean. The then-part e2e_2 and the else-part e3e_3 are both expected to conform to the expected type of the conditional expression. The type of the conditional expression is the weak least upper bound of the types of e2e_2 and e3e_3. A semicolon preceding the else symbol of a conditional expression is ignored.

The conditional expression is evaluated by evaluating first e1e_1. If this evaluates to true, the result of evaluating e2e_2 is returned, otherwise the result of evaluating e3e_3 is returned.

A short form of the conditional expression eliminates the else-part. The conditional expression if (e1e_1) e2e_2 is evaluated as if it was if (e1e_1) e2e_2 else ().

While Loop Expressions

Expr1          ::=  ‘while’ ‘(’ Expr ‘)’ {nl} Expr

The while loop expression while (e1e_1) e2e_2 is typed and evaluated as if it was an application of whileLoop (e1e_1) (e2e_2) where the hypothetical method whileLoop is defined as follows.

def whileLoop(cond: => Boolean)(body: => Unit): Unit  =
  if (cond) { body ; whileLoop(cond)(body) } else {}

Do Loop Expressions

Expr1          ::=  ‘do’ Expr [semi] ‘while’ ‘(’ Expr ‘)’

The do loop expression do e1e_1 while (e2e_2) is typed and evaluated as if it was the expression (e1e_1 ; while (e2e_2) e1e_1). A semicolon preceding the while symbol of a do loop expression is ignored.

For Comprehensions and For Loops

Expr1          ::=  ‘for’ (‘(’ Enumerators ‘)’ | ‘{’ Enumerators ‘}’)
                       {nl} [‘yield’] Expr
Enumerators    ::=  Generator {semi Generator}
Generator      ::=  [‘case’] Pattern1 ‘<-’ Expr {[semi] Guard | semi Pattern1 ‘=’ Expr}
Guard          ::=  ‘if’ PostfixExpr

A for loop for (enums&ThinSpace;\mathit{enums}\,) ee executes expression ee for each binding generated by the enumerators enums\mathit{enums}. A for comprehension for (enums&ThinSpace;\mathit{enums}\,) yield ee evaluates expression ee for each binding generated by the enumerators enums\mathit{enums} and collects the results. An enumerator sequence always starts with a generator; this can be followed by further generators, value definitions, or guards.

A generator pp <- ee produces bindings from an expression ee which is matched in some way against pattern pp. Optionally, case can appear in front of a generator pattern, this has no meaning in Scala 2 but will be required in Scala 3 if p is not irrefutable.

A value definition pp = ee binds the value name pp (or several names in a pattern pp) to the result of evaluating the expression ee. A guard if ee contains a boolean expression which restricts enumerated bindings. The precise meaning of generators and guards is defined by translation to invocations of four methods: map, withFilter, flatMap, and foreach. These methods can be implemented in different ways for different carrier types.

The translation scheme is as follows. In a first step, every generator pp <- ee, where pp is not irrefutable for the type of ee is replaced by

pp <- ee.withFilter { case pp => true; case _ => false }

Then, the following rules are applied repeatedly until all comprehensions have been eliminated.

Example

The following code produces all pairs of numbers between 11 and n1n-1 whose sums are prime.

for  { i <- 1 until n
       j <- 1 until i
       if isPrime(i+j)
} yield (i, j)

The for comprehension is translated to:

(1 until n)
  .flatMap {
     case i => (1 until i)
       .withFilter { j => isPrime(i+j) }
       .map { case j => (i, j) } }
Example

For comprehensions can be used to express vector and matrix algorithms concisely. For instance, here is a method to compute the transpose of a given matrix:

def transpose[A](xss: Array[Array[A]]) = {
  for (i <- Array.range(0, xss(0).length)) yield
    for (xs <- xss) yield xs(i)
}

Here is a method to compute the scalar product of two vectors:

def scalprod(xs: Array[Double], ys: Array[Double]) = {
  var acc = 0.0
  for ((x, y) <- xs zip ys) acc = acc + x * y
  acc
}

Finally, here is a method to compute the product of two matrices. Compare with the imperative version.

def matmul(xss: Array[Array[Double]], yss: Array[Array[Double]]) = {
  val ysst = transpose(yss)
  for (xs <- xss) yield
    for (yst <- ysst) yield
      scalprod(xs, yst)
}

The code above makes use of the fact that map, flatMap, withFilter, and foreach are defined for instances of class scala.Array.

Return Expressions

Expr1      ::=  ‘return’ [Expr]

A return expression return ee must occur inside the body of some enclosing user defined method. The innermost enclosing method in a source program, mm, must have an explicitly declared result type, and the type of ee must conform to it.

The return expression evaluates the expression ee and returns its value as the result of mm. The evaluation of any statements or expressions following the return expression is omitted. The type of a return expression is scala.Nothing.

The expression ee may be omitted. The return expression return is type-checked and evaluated as if it were return ().

Returning from the method from within a nested function may be implemented by throwing and catching a scala.runtime.NonLocalReturnControl. Any exception catches between the point of return and the enclosing methods might see and catch that exception. A key comparison makes sure that this exception is only caught by the method instance which is terminated by the return.

If the return expression is itself part of an anonymous function, it is possible that the enclosing method mm has already returned before the return expression is executed. In that case, the thrown scala.runtime.NonLocalReturnControl will not be caught, and will propagate up the call stack.

Throw Expressions

Expr1      ::=  ‘throw’ Expr

A throw expression throw ee evaluates the expression ee. The type of this expression must conform to Throwable. If ee evaluates to an exception reference, evaluation is aborted with the thrown exception. If ee evaluates to null, evaluation is instead aborted with a NullPointerException. If there is an active try expression which handles the thrown exception, evaluation resumes with the handler; otherwise the thread executing the throw is aborted. The type of a throw expression is scala.Nothing.

Try Expressions

Expr1 ::=  ‘try’ Expr [‘catch’ Expr] [‘finally’ Expr]

A try expression is of the form try { bb } catch hh where the handler hh is usually a pattern matching anonymous function

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

This expression is evaluated by evaluating the block bb. If evaluation of bb does not cause an exception to be thrown, the result of bb is returned. Otherwise the handler hh is applied to the thrown exception. If the handler contains a case matching the thrown exception, the first such case is invoked. If the handler contains no case matching the thrown exception, the exception is re-thrown. More generally, if the handler is a PartialFunction, it is applied only if it is defined at the given exception.

Let pt\mathit{pt} be the expected type of the try expression. The block bb is expected to conform to pt\mathit{pt}. The handler hh is expected conform to type scala.Function[scala.Throwable, pt&ThinSpace;\mathit{pt}\,]. The type of the try expression is the weak least upper bound of the type of bb and the result type of hh.

A try expression try { bb } finally ee evaluates the block bb. If evaluation of bb does not cause an exception to be thrown, the expression ee is evaluated. If an exception is thrown during evaluation of ee, the evaluation of the try expression is aborted with the thrown exception. If no exception is thrown during evaluation of ee, the result of bb is returned as the result of the try expression.

If an exception is thrown during evaluation of bb, the finally block ee is also evaluated. If another exception ee is thrown during evaluation of ee, evaluation of the try expression is aborted with the thrown exception. If no exception is thrown during evaluation of ee, the original exception thrown in bb is re-thrown once evaluation of ee has completed. The block bb is expected to conform to the expected type of the try expression. The finally expression ee is expected to conform to type Unit.

A try expression try { bb } catch e1e_1 finally e2e_2 is a shorthand for try { try { bb } catch e1e_1 } finally e2e_2.

Anonymous Functions

Expr            ::=  (Bindings | [‘implicit’] (id | ‘_’)) ‘=>’ Expr
ResultExpr      ::=  (Bindings | [‘implicit’] (id | ‘_’) [‘:’ CompoundType]) ‘=>’ Block
Bindings        ::=  ‘(’ Binding {‘,’ Binding} ‘)’
Binding         ::=  (id | ‘_’) [‘:’ Type]

The anonymous function of arity nn, (x1x_1: T1,,xnT_1 , \ldots , x_n: TnT_n) => e maps parameters xix_i of types TiT_i to a result given by expression ee. The scope of each formal parameter xix_i is ee. Formal parameters must have pairwise distinct names.

In the case of a single untyped formal parameter, (x&ThinSpace;x\,) => ee can be abbreviated to xx => ee. If an anonymous function (xx: T&ThinSpace;T\,) => ee with a single typed parameter appears as the result expression of a block, it can be abbreviated to xx: TT => e.

A formal parameter may also be a wildcard represented by an underscore _. In that case, a fresh name for the parameter is chosen arbitrarily.

A named parameter of an anonymous function may be optionally preceded by an implicit modifier. In that case the parameter is labeled implicit; however the parameter section itself does not count as an implicit parameter section. Hence, arguments to anonymous functions always have to be given explicitly.

Translation

If the expected type of the anonymous function is of the shape scala.Functionnn[S1,,SnS_1 , \ldots , S_n, R&ThinSpace;R\,], or can be SAM-converted to such a function type, the type TiT_i of a parameter xix_i can be omitted, as far as SiS_i is defined in the expected type, and TiT_i = SiS_i is assumed. Furthermore, the expected type when type checking ee is RR.

If there is no expected type for the function literal, all formal parameter types TiT_i must be specified explicitly, and the expected type of ee is undefined. The type of the anonymous function is scala.Functionnn[T1,,TnT_1 , \ldots , T_n, R&ThinSpace;R\,], where RR is the packed type of ee. RR must be equivalent to a type which does not refer to any of the formal parameters xix_i.

The eventual run-time value of an anonymous function is determined by the expected type:

The standard anonymous function evaluates in the same way as the following instance creation expression:

new scala.Functionnn[T1,,TnT_1 , \ldots , T_n, TT] {
  def apply(x1x_1: T1,,xnT_1 , \ldots , x_n: TnT_n): TT = ee
}

The same evaluation holds for a SAM type, except that the instantiated type is given by the SAM type, and the implemented method is the single abstract method member of this type.

The underlying platform may provide more efficient ways of constructing these instances, such as Java 8's invokedynamic bytecode and LambdaMetaFactory class.

When a PartialFunction is required, an additional member isDefinedAt is synthesized, which simply returns true. However, if the function literal has the shape x => x match { $\ldots$ }, then isDefinedAt is derived from the pattern match in the following way: each case from the match expression evaluates to true, and if there is no default case, a default case is added that evaluates to false. For more details on how that is implemented see "Pattern Matching Anonymous Functions".

Example

Examples of anonymous functions:

x => x                             // The identity function

f => g => x => f(g(x))             // Curried function composition

(x: Int,y: Int) => x + y           // A summation function

() => { count += 1; count }        // The function which takes an
                                   // empty parameter list ()(),
                                   // increments a non-local variable
                                   // `count' and returns the new value.

_ => 5                             // The function that ignores its argument
                                   // and always returns 5.

Placeholder Syntax for Anonymous Functions

SimpleExpr1  ::=  ‘_’

An expression (of syntactic category Expr) may contain embedded underscore symbols _ at places where identifiers are legal. Such an expression represents an anonymous function where subsequent occurrences of underscores denote successive parameters.

Define an underscore section to be an expression of the form _:TT where TT is a type, or else of the form _, provided the underscore does not appear as the expression part of a type ascription _:TT.

An expression ee of syntactic category Expr binds an underscore section uu, if the following two conditions hold: (1) ee properly contains uu, and (2) there is no other expression of syntactic category Expr which is properly contained in ee and which itself properly contains uu.

If an expression ee binds underscore sections u1,,unu_1 , \ldots , u_n, in this order, it is equivalent to the anonymous function (u1u&#x27;_1, ... unu&#x27;_n) => ee&#x27; where each uiu_i&#x27; results from uiu_i by replacing the underscore with a fresh identifier and ee&#x27; results from ee by replacing each underscore section uiu_i by uiu_i&#x27;.

Example

The anonymous functions in the left column use placeholder syntax. Each of these is equivalent to the anonymous function on its right.

_ + 1 x => x + 1
_ * _ (x1, x2) => x1 * x2
(_: Int) * 2 (x: Int) => (x: Int) * 2
if (_) x else y z => if (z) x else y
_.map(f) x => x.map(f)
_.map(_ + 1) x => x.map(y => y + 1)

Constant Expressions

Constant expressions are expressions that the Scala compiler can evaluate to a constant. The definition of "constant expression" depends on the platform, but they include at least the expressions of the following forms:

Statements

BlockStat    ::=  Import
               |  {Annotation} [‘implicit’] [‘lazy’] Def
               |  {Annotation} {LocalModifier} TmplDef
               |  Expr1
               |
TemplateStat ::=  Import
               |  {Annotation} {Modifier} Def
               |  {Annotation} {Modifier} Dcl
               |  Expr
               |

Statements occur as parts of blocks and templates. A statement can be an import, a definition or an expression, or it can be empty. Statements used in the template of a class definition can also be declarations. An expression that is used as a statement can have an arbitrary value type. An expression statement ee is evaluated by evaluating ee and discarding the result of the evaluation.

Block statements may be definitions which bind local names in the block. The only modifier allowed in all block-local definitions is implicit. When prefixing a class or object definition, modifiers abstract, final, and sealed are also permitted.

Evaluation of a statement sequence entails evaluation of the statements in the order they are written.

Implicit Conversions

Implicit conversions can be applied to expressions whose type does not match their expected type, to qualifiers in selections, and to unapplied methods. The available implicit conversions are given in the next two sub-sections.

Value Conversions

The following seven implicit conversions can be applied to an expression ee which has some value type TT and which is type-checked with some expected type pt\mathit{pt}.

Static Overloading Resolution

If an expression denotes several possible members of a class, overloading resolution is applied to pick a unique member.

Type Instantiation

An expression ee of polymorphic type

[a1a_1 >: L1L_1 <: U1,,anU_1 , \ldots , a_n >: LnL_n <: UnU_n]TT

which does not appear as the function part of a type application is converted to a type instance of TT by determining with local type inference instance types T1,,TnT_1 , \ldots , T_n for the type variables a1,,ana_1 , \ldots , a_n and implicitly embedding ee in the type application ee[T1,,TnT_1 , \ldots , T_n].

Numeric Widening

If ee has a primitive number type which weakly conforms to the expected type, it is widened to the expected type using one of the numeric conversion methods toShort, toChar, toInt, toLong, toFloat, toDouble defined in the standard library.

Since conversions from Int to Float and from Long to Float or Double may incur a loss of precision, those implicit conversions are deprecated. The conversion is permitted for literals if the original value can be recovered, that is, if conversion back to the original type produces the original value.

Numeric Literal Narrowing

If the expected type is Byte, Short or Char, and the expression ee is an integer literal fitting in the range of that type, it is converted to the same literal in that type.

Value Discarding

If ee has some value type and the expected type is Unit, ee is converted to the expected type by embedding it in the term { ee; () }.

SAM conversion

An expression (p1, ..., pN) => body of function type (T1, ..., TN) => T is sam-convertible to the expected type S if the following holds:

Note that a function literal that targets a SAM is not necessarily compiled to the above instance creation expression. This is platform-dependent.

It follows that:

Finally, we impose some implementation restrictions (these may be lifted in future releases):

View Application

If none of the previous conversions applies, and ee's type does not conform to the expected type pt\mathit{pt}, it is attempted to convert ee to the expected type with a view.

Selection on Dynamic

If none of the previous conversions applies, and ee is a prefix of a selection e.xe.x, and ee's type conforms to class scala.Dynamic, then the selection is rewritten according to the rules for dynamic member selection.

Method Conversions

The following four implicit conversions can be applied to methods which are not applied to some argument list.

Evaluation

A parameterless method mm of type => TT is always converted to type TT by evaluating the expression to which mm is bound.

Implicit Application

If the method takes only implicit parameters, implicit arguments are passed following the rules here.

Eta Expansion

Otherwise, if the method is not a constructor, and the expected type pt\mathit{pt} is a function type, or, for methods of non-zero arity, a type sam-convertible to a function type, (Ts)T(\mathit{Ts}&#x27;) \Rightarrow T&#x27;, eta-expansion is performed on the expression ee.

(The exception for zero-arity methods is to avoid surprises due to unexpected sam conversion.)

Empty Application

Otherwise, if ee has method type ()T()T, it is implicitly applied to the empty argument list, yielding e()e().

Overloading Resolution

If an identifier or selection ee references several members of a class, the context of the reference is used to identify a unique member. The way this is done depends on whether or not ee is used as a function. Let A\mathscr{A} be the set of members referenced by ee.

Assume first that ee appears as a function in an application, as in ee(e1,,eme_1 , \ldots , e_m).

One first determines the set of functions that is potentially applicable based on the shape of the arguments.

The shape of an argument expression ee, written shape(e)\mathit{shape}(e), is a type that is defined as follows:

Let B\mathscr{B} be the set of alternatives in A\mathscr{A} that are applicable to expressions (e1,,en)(e_1 , \ldots , e_n) of types (shape(e1),,shape(en))(\mathit{shape}(e_1) , \ldots , \mathit{shape}(e_n)). If there is precisely one alternative in B\mathscr{B}, that alternative is chosen.

Otherwise, let S1,,SmS_1 , \ldots , S_m be the list of types obtained by typing each argument as follows.

Normally, an argument is typed without an expected type, except when all alternatives explicitly specify the same parameter type for this argument (a missing parameter type, due to e.g. arity differences, is taken as NoType, thus resorting to no expected type), or when trying to propagate more type information to aid inference of higher-order function parameter types, as explained next.

The intuition for higher-order function parameter type inference is that all arguments must be of a function-like type (PartialFunction, FunctionN or some equivalent SAM type), which in turn must define the same set of higher-order argument types, so that they can safely be used as the expected type of a given argument of the overloaded method, without unduly ruling out any alternatives. The intent is not to steer overloading resolution, but to preserve enough type information to steer type inference of the arguments (a function literal or eta-expanded method) to this overloaded method.

Note that the expected type drives eta-expansion (not performed unless a function-like type is expected), as well as inference of omitted parameter types of function literals.

More precisely, an argument eie_i is typed with an expected type that is derived from the iith argument type found in each alternative (call these TijT_{ij} for alternative jj and argument position ii) when all TijT_{ij} are function types (A1j,...,Anj)=&gt;?(A_{1j},..., A_{nj}) =&gt; ? (or the equivalent PartialFunction, or SAM) of some arity nn, and their argument types AkjA_{kj} are identical across all overloads jj for a given kk. Then, the expected type for eie_i is derived as follows:

For every member mm in B\mathscr{B} one determines whether it is applicable to expressions (e1,,eme_1 , \ldots , e_m) of types S1,,SmS_1, \ldots , S_m.

It is an error if none of the members in B\mathscr{B} is applicable. If there is one single applicable alternative, that alternative is chosen. Otherwise, let CC\mathscr{CC} be the set of applicable alternatives which don't employ any default argument in the application to e1,,eme_1 , \ldots , e_m.

It is again an error if CC\mathscr{CC} is empty. Otherwise, one chooses the most specific alternative among the alternatives in CC\mathscr{CC}, according to the following definition of being "as specific as", and "more specific than":

The relative weight of an alternative AA over an alternative BB is a number from 0 to 2, defined as the sum of

A class or object CC is derived from a class or object DD if one of the following holds:

An alternative AA is more specific than an alternative BB if the relative weight of AA over BB is greater than the relative weight of BB over AA.

It is an error if there is no alternative in CC\mathscr{CC} which is more specific than all other alternatives in CC\mathscr{CC}.

Assume next that ee appears as a function in a type application, as in ee[targs&ThinSpace;\mathit{targs}\,]. Then all alternatives in A\mathscr{A} which take the same number of type parameters as there are type arguments in targs\mathit{targs} are chosen. It is an error if no such alternative exists. If there are several such alternatives, overloading resolution is applied again to the whole expression ee[targs&ThinSpace;\mathit{targs}\,].

Assume finally that ee does not appear as a function in either an application or a type application. If an expected type is given, let B\mathscr{B} be the set of those alternatives in A\mathscr{A} which are compatible to it. Otherwise, let B\mathscr{B} be the same as A\mathscr{A}. In this last case we choose the most specific alternative among all alternatives in B\mathscr{B}. It is an error if there is no alternative in B\mathscr{B} which is more specific than all other alternatives in B\mathscr{B}.

Example

Consider the following definitions:

class A extends B {}
def f(x: B, y: B) = \ldots
def f(x: A, y: B) = \ldots
val a: A
val b: B

Then the application f(b, b) refers to the first definition of ff whereas the application f(a, a) refers to the second. Assume now we add a third overloaded definition

def f(x: B, y: A) = \ldots

Then the application f(a, a) is rejected for being ambiguous, since no most specific applicable signature exists.

Local Type Inference

Local type inference infers type arguments to be passed to expressions of polymorphic type. Say ee is of type [a1a_1 >: L1L_1 <: U1,,anU_1, \ldots , a_n >: LnL_n <: UnU_n]TT and no explicit type parameters are given.

Local type inference converts this expression to a type application ee[T1,,TnT_1 , \ldots , T_n]. The choice of the type arguments T1,,TnT_1 , \ldots , T_n depends on the context in which the expression appears and on the expected type pt\mathit{pt}. There are three cases.

Case 1: Selections

If the expression appears as the prefix of a selection with a name xx, then type inference is deferred to the whole expression e.xe.x. That is, if e.xe.x has type SS, it is now treated as having type [a1a_1 >: L1L_1 <: U1,,anU_1 , \ldots , a_n >: LnL_n <: UnU_n]SS, and local type inference is applied in turn to infer type arguments for a1,,ana_1 , \ldots , a_n, using the context in which e.xe.x appears.

Case 2: Values

If the expression ee appears as a value without being applied to value arguments, the type arguments are inferred by solving a constraint system which relates the expression's type TT with the expected type pt\mathit{pt}. Without loss of generality we can assume that TT is a value type; if it is a method type we apply eta-expansion to convert it to a function type. Solving means finding a substitution σ\sigma of types TiT_i for the type parameters aia_i such that

It is a compile time error if no such substitution exists. If several substitutions exist, local-type inference will choose for each type variable aia_i a minimal or maximal type TiT_i of the solution space. A maximal type TiT_i will be chosen if the type parameter aia_i appears contravariantly in the type TT of the expression. A minimal type TiT_i will be chosen in all other situations, i.e. if the variable appears covariantly, non-variantly or not at all in the type TT. We call such a substitution an optimal solution of the given constraint system for the type TT.

Case 3: Methods

The last case applies if the expression ee appears in an application e(d1,,dm)e(d_1 , \ldots , d_m). In that case TT is a method type (p1:R1,,pm:Rm)T(p_1:R_1 , \ldots , p_m:R_m)T&#x27;. Without loss of generality we can assume that the result type TT&#x27; is a value type; if it is a method type we apply eta-expansion to convert it to a function type. One computes first the types SjS_j of the argument expressions djd_j, using two alternative schemes. Each argument expression djd_j is typed first with the expected type RjR_j, in which the type parameters a1,,ana_1 , \ldots , a_n are taken as type constants. If this fails, the argument djd_j is typed instead with an expected type RjR_j&#x27; which results from RjR_j by replacing every type parameter in a1,,ana_1 , \ldots , a_n with undefined.

In a second step, type arguments are inferred by solving a constraint system which relates the method's type with the expected type pt\mathit{pt} and the argument types S1,,SmS_1 , \ldots , S_m. Solving the constraint system means finding a substitution σ\sigma of types TiT_i for the type parameters aia_i such that

It is a compile time error if no such substitution exists. If several solutions exist, an optimal one for the type TT&#x27; is chosen.

All or parts of an expected type pt\mathit{pt} may be undefined. The rules for conformance are extended to this case by adding the rule that for any type TT the following two statements are always true: undefined&lt;:T\mathit{undefined} &lt;: T and T&lt;:undefinedT &lt;: \mathit{undefined}

It is possible that no minimal or maximal solution for a type variable exists, in which case a compile-time error results. Because &lt;:&lt;: is a pre-order, it is also possible that a solution set has several optimal solutions for a type. In that case, a Scala compiler is free to pick any one of them.

Example

Consider the two methods:

def cons[A](x: A, xs: List[A]): List[A] = x :: xs
def nil[B]: List[B] = Nil

and the definition

val xs = cons(1, nil)

The application of cons is typed with an undefined expected type. This application is completed by local type inference to cons[Int](1, nil). Here, one uses the following reasoning to infer the type argument Int for the type parameter a:

First, the argument expressions are typed. The first argument 1 has type Int whereas the second argument nil is itself polymorphic. One tries to type-check nil with an expected type List[a]. This leads to the constraint system

List[b?] <: List[a]

where we have labeled b? with a question mark to indicate that it is a variable in the constraint system. Because class List is covariant, the optimal solution of this constraint is

b = scala.Nothing

In a second step, one solves the following constraint system for the type parameter a of cons:

Int <: a?
List[scala.Nothing] <: List[a?]
List[a?] <: undefined\mathit{undefined}

The optimal solution of this constraint system is

a = Int

so Int is the type inferred for a.

Example

Consider now the definition

val ys = cons("abc", xs)

where xs is defined of type List[Int] as before. In this case local type inference proceeds as follows.

First, the argument expressions are typed. The first argument "abc" has type String. The second argument xs is first tried to be typed with expected type List[a]. This fails, as List[Int] is not a subtype of List[a]. Therefore, the second strategy is tried; xs is now typed with expected type List[undefined\mathit{undefined}]. This succeeds and yields the argument type List[Int].

In a second step, one solves the following constraint system for the type parameter a of cons:

String <: a?
List[Int] <: List[a?]
List[a?] <: undefined\mathit{undefined}

The optimal solution of this constraint system is

a = scala.Any

so scala.Any is the type inferred for a.

Eta Expansion

Eta-expansion converts an expression of method type to an equivalent expression of function type. It proceeds in two steps.

First, one identifies the maximal sub-expressions of ee; let's say these are e1,,eme_1 , \ldots , e_m. For each of these, one creates a fresh name xix_i. Let ee&#x27; be the expression resulting from replacing every maximal subexpression eie_i in ee by the corresponding fresh name xix_i. Second, one creates a fresh name yiy_i for every argument type TiT_i of the method (i=1,,ni = 1 , \ldots , n). The result of eta-conversion is then:

{ val x1x_1 = e1e_1;
  \ldots
  val xmx_m = eme_m;
  (y1:T1,,yn:Tny_1: T_1 , \ldots , y_n: T_n) => ee&#x27;(y1,,yny_1 , \ldots , y_n)
}

The behavior of call-by-name parameters is preserved under eta-expansion: the corresponding actual argument expression, a sub-expression of parameterless method type, is not evaluated in the expanded block.

Dynamic Member Selection

The standard Scala library defines a marker trait scala.Dynamic. Subclasses of this trait are able to intercept selections and applications on their instances by defining methods of the names applyDynamic, applyDynamicNamed, selectDynamic, and updateDynamic.

The following rewrites are performed, assuming ee's type conforms to scala.Dynamic, and the original expression does not type check under the normal rules, as specified fully in the relevant subsection of implicit conversion:

If any arguments are named in the application (one of the xi is of the shape arg = x), their name is preserved as the first component of the pair passed to applyDynamicNamed (for missing names, "" is used):

Finally:

None of these methods are actually defined in the scala.Dynamic, so that users are free to define them with or without type parameters, or implicit arguments.