Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the difference between multiple parameters lists and multiple parameters per list in Scala?

In Scala one can write (curried?) functions like this

def curriedFunc(arg1: Int) (arg2: String) = { ... } 

What is the difference between the above curriedFunc function definition with two parameters lists and functions with multiple parameters in a single parameter list:

def curriedFunc(arg1: Int, arg2: String) = { ... } 

From a mathematical point of view this is (curriedFunc(x))(y) and curriedFunc(x,y) but I can write def sum(x) (y) = x + y and the same will be def sum2(x, y) = x + y

I know only one difference - this is partially applied functions. But both ways are equivalent for me.

Are there any other differences?

like image 732
den bardadym Avatar asked Jul 23 '11 20:07

den bardadym


People also ask

What are parameter lists?

The parameter list of a function describes the number and types of the arguments that the function accepts, and the number and types of the values it returns. The parameter list of a generic function is used to define the overall protocol of the generic function.

What is multiple parameter?

Note that when you are working with multiple parameters, the function call must have the same number of arguments as there are parameters, and the arguments must be passed in the same order.

Can functions have multiple parameters?

Luckily, you can write functions that take in more than one parameter by defining as many parameters as needed, for example: def function_name(data_1, data_2):

How many parameters can a method take?

Parameters are specified after the method name, inside the parentheses. You can add as many parameters as you want, just separate them with a comma.


2 Answers

Strictly speaking, this is not a curried function, but a method with multiple argument lists, although admittedly it looks like a function.

As you said, the multiple arguments lists allow the method to be used in the place of a partially applied function. (Sorry for the generally silly examples I use)

object NonCurr {   def tabulate[A](n: Int, fun: Int => A) = IndexedSeq.tabulate(n)(fun) }  NonCurr.tabulate[Double](10, _)            // not possible val x = IndexedSeq.tabulate[Double](10) _  // possible. x is Function1 now x(math.exp(_))                             // complete the application 

Another benefit is that you can use curly braces instead of parenthesis which looks nice if the second argument list consists of a single function, or thunk. E.g.

NonCurr.tabulate(10, { i => val j = util.Random.nextInt(i + 1); i - i % 2 }) 

versus

IndexedSeq.tabulate(10) { i =>   val j = util.Random.nextInt(i + 1)   i - i % 2 } 

Or for the thunk:

IndexedSeq.fill(10) {   println("debug: operating the random number generator")   util.Random.nextInt(99) } 

Another advantage is, you can refer to arguments of a previous argument list for defining default argument values (although you could also say it's a disadvantage that you cannot do that in single list :)

// again I'm not very creative with the example, so forgive me def doSomething(f: java.io.File)(modDate: Long = f.lastModified) = ??? 

Finally, there are three other application in an answer to related post Why does Scala provide both multiple parameters lists and multiple parameters per list? . I will just copy them here, but the credit goes to Knut Arne Vedaa, Kevin Wright, and extempore.

First: you can have multiple var args:

def foo(as: Int*)(bs: Int*)(cs: Int*) = as.sum * bs.sum * cs.sum 

...which would not be possible in a single argument list.

Second, it aids the type inference:

def foo[T](a: T, b: T)(op: (T,T) => T) = op(a, b) foo(1, 2){_ + _}   // compiler can infer the type of the op function  def foo2[T](a: T, b: T, op: (T,T) => T) = op(a, b) foo2(1, 2, _ + _)  // compiler too stupid, unfortunately 

And last, this is the only way you can have implicit and non implicit args, as implicit is a modifier for a whole argument list:

def gaga [A](x: A)(implicit mf: Manifest[A]) = ???   // ok def gaga2[A](x: A, implicit mf: Manifest[A]) = ???   // not possible 
like image 131
0__ Avatar answered Oct 19 '22 04:10

0__


There's another difference that was not covered by 0__'s excellent answer: default parameters. A parameter from one parameter list can be used when computing the default in another parameter list, but not in the same one.

For example:

def f(x: Int, y: Int = x * 2) = x + y // not valid def g(x: Int)(y: Int = x * 2) = x + y // valid 
like image 38
Daniel C. Sobral Avatar answered Oct 19 '22 02:10

Daniel C. Sobral