Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

When using the following syntax to define functions with currying enabled:

def sum(x: Int)(y: Int)(z: Int) = x + y + z

one still has to suffix any calls to curried calls of sum with _:

sum _
sum(3) _
sum(3)(2) _

otherwise the compiler will complain.

So I resorted to:

val sum = (x: Int) => (y: Int) => (z: Int) => x + y + z

which works without the _.

Now the question: why does the multiple-parameter-lists version require _ in order for currying to kick in? Why aren't the semantics of those 2 versions equivalent in all contexts?

Also, is the latter version somehow discouraged? Does it suffer from any caveats?

share|improve this question
3  

1 Answer 1

up vote 0 down vote accepted

The reason why those two semantics are different, is that methods and functions are not the same thing.

Methods are full-fledges JVM methods, whereas functions are values (i.e. instance of classes like Function1, Function2 and so on).

So

def sum(x: Int)(y: Int)(z: Int) = x + y + z

and

val sum = (x: Int) => (y: Int) => (z: Int) => x + y + z

may seem identical, but the first is an method, while the second is a Function1[Int, Function1[Int, Function1[Int, Int]]]

When you try to use a method where a function value is expected, the compiler automatically converts it to a function (a process called eta-expansion).

However, there are case in which the compiler doesn't eta-expand the methods automatically, such as the cases you exposed, in which you explicitly want to partially apply it.

Using _ triggers the eta-expansion, so a method is converted to a function, and everybody is happy.

According to the scala specification, you could also annotate the expected type, in which case the expansion is performed automatically:

def sum(x: Int)(y: Int)(z: Int) = x + y + z
val sumFunction: Int => Int => Int => Int = sum

which is the same reason why

def sum(x: Int, y: Int) = x + y
List(1,2,3).reduce(sum)

works, i.e. we're passing a method where a function is explicitly required.

Here's a more in-depth discussion of when scala performs an eta-expansion: http://stackoverflow.com/a/2394063/846273


Concerning the choice of which to adopt, I'll point you to this answer, which is very exhaustive.

share|improve this answer
    
I just fail to see why the compiler would require _ if I do stuff like val x = foo _ — does it think I might have forgotten to pass the right number of arguments to foo? As to the rest of your answer, I'm already aware of all the points :) –  Erik Allik Oct 2 '14 at 16:04
    
That's a rather arbitrary design decision. From the scala specification you can either pass _ or explicitly annotate the type (val x: Int => Int => Int => Int = sum). Here's a relevant discussion: stackoverflow.com/questions/2363013/… –  Gabriele Petronella Oct 2 '14 at 16:09

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.