Tour of Scala

Multiple Parameter Lists

Language

Methods may have multiple parameter lists.

Example

Here is an example, as defined on the Iterable trait in Scala’s collections API:

traitIterable[A]{...deffoldLeft[B](z:B)(op:(B,A)=>B):B...}
traitIterable[A]:...deffoldLeft[B](z:B)(op:(B,A)=>B):B...

foldLeft applies a two-parameter function op to an initial value z and all elements of this collection, going left to right. Shown below is an example of its usage.

Starting with an initial value of 0, foldLeft here applies the function (m, n) => m + n to each element in the List and the previous accumulated value.

valnumbers=List(1,2,3,4,5,6,7,8,9,10)valres=numbers.foldLeft(0)((m,n)=>m+n)println(res)// 55

Use cases

Suggested use cases for multiple parameter lists include:

Drive type inference

It so happens that in Scala, type inference proceeds one parameter list at a time. Say you have the following method:

deffoldLeft1[A, B](as:List[A],b0:B,op:(B,A)=>B)=???

Then you’d like to call it in the following way, but will find that it doesn’t compile:

defnotPossible=foldLeft1(numbers,0,_+_)

you will have to call it like one of the below ways:

deffirstWay=foldLeft1[Int, Int](numbers,0,_+_)defsecondWay=foldLeft1(numbers,0,(a:Int,b:Int)=>a+b)

That’s because Scala won’t be able to infer the type of the function _ + _, as it’s still inferring A and B. By moving the parameter op to its own parameter list, A and B are inferred in the first parameter list. These inferred types will then be available to the second parameter list and _ + _ will match the inferred type (Int, Int) => Int

deffoldLeft2[A, B](as:List[A],b0:B)(op:(B,A)=>B)=???defpossible=foldLeft2(numbers,0)(_+_)

This definition doesn’t need any type hints and can infer all of its type parameters.

Implicit parameters

To specify only certain parameters as implicit, they must be placed in their own implicit parameter list.

An example of this is:

defexecute(arg:Int)(implicitec:scala.concurrent.ExecutionContext)=???
defexecute(arg:Int)(usingec:scala.concurrent.ExecutionContext)=???

Partial application

When a method is called with a fewer number of parameter lists, then this will yield a function taking the missing parameter lists as its arguments. This is formally known as partial application.

For example,

valnumbers=List(1,2,3,4,5,6,7,8,9,10)valnumberFunc=numbers.foldLeft(List[Int]())_valsquares=numberFunc((xs,x)=>xs:+x*x)println(squares)// List(1, 4, 9, 16, 25, 36, 49, 64, 81, 100)valcubes=numberFunc((xs,x)=>xs:+x*x*x)println(cubes)// List(1, 8, 27, 64, 125, 216, 343, 512, 729, 1000)
valnumbers=List(1,2,3,4,5,6,7,8,9,10)valnumberFunc=numbers.foldLeft(List[Int]())valsquares=numberFunc((xs,x)=>xs:+x*x)println(squares)// List(1, 4, 9, 16, 25, 36, 49, 64, 81, 100)valcubes=numberFunc((xs,x)=>xs:+x*x*x)println(cubes)// List(1, 8, 27, 64, 125, 216, 343, 512, 729, 1000)

Comparison with “currying”

You may sometimes see a method with multiple parameter lists referred to as “curried”.

As the Wikipedia article on currying states,

Currying is the technique of converting a function that takes multiple arguments into a sequence of functions that each takes a single argument

We discourage the use of the word “curry” in reference to Scala’s multiple parameter lists, for two reasons:

1) In Scala, multiple parameters and multiple parameter lists are specified and implemented directly, as part of the language, rather being derived from single-parameter functions.

2) There is danger of confusion with the Scala standard library’s curried and uncurried methods, which don’t involve multiple parameter lists at all.

Regardless, there are certainly similarities to be found between multiple parameter lists and currying. Though they are different at the definition site, the call site might nonetheless look identical, as in this example:

// version with multiple parameter listsdefaddMultiple(n1:Int)(n2:Int)=n1+n2// two different ways of arriving at a curried version insteaddefadd(n1:Int,n2:Int)=n1+n2valaddCurried1=(add_).curriedvaladdCurried2=(n1:Int)=>(n2:Int)=>n1+n2// regardless, all three call sites are identicaladdMultiple(3)(4)// 7addCurried1(3)(4)// 7addCurried2(3)(4)// 7

Contributors to this page:

close