Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
452 views
in Technique[技术] by (71.8m points)

currying - 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?

Question&Answers:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...