1

I'm starting to learn a little Scala, and I basically understand functions that return functions and currying, but I've seen two syntaxes for doing this, and I'd like to better understand the differences, and maybe a little of theory behind what's going on.

In the first method (using =>) I can curry the function by just specifying the argument to be bound to variable x. However when I try to do this with the second approach, the compiler tells me I need to specify the _ wild card for the second argument.

I understand what I need to do but I am not sure why I need to do things this way. Can someone please tell me what the Scala compiler is doing here?

First Method using =>

def add(x:Int) = (y:Int) => x + (-y)
add: (x: Int)Int => Int

scala> def adder = add(100)   // x is bound to 100 in the returned closure
adder: Int => Int

scala> adder(1)
res42: Int = 99

Second Method using one arg list followed by another

scala> def add2(x:Int)(y:Int) :  Int =  x + y
add2: (x: Int)(y: Int)Int

scala> def  adder2 = add2(100)
<console>:9: error: missing arguments for method add2;
follow this method with `_' if you want to treat it 
 as a partially applied function

       def  adder2 = add2(100)
                         ^

scala> def  adder2 = add2(100) _    // Okay, here is the '_'
adder2: Int => Int

scala> adder2(1)                    // Now i can call the curried function
res43: Int = 101
Ben Reich
  • 16,222
  • 2
  • 38
  • 59
Chris Bedford
  • 2,560
  • 3
  • 28
  • 60

1 Answers1

4

What you're seeing is the difference between method types and function types. It's a subtle and sometimes confusing difference. This answer contains a pretty comprehensive explanation of the differences between method types and function types. Here's some of the most relevant points for your question:

A Function Type is (roughly) a type of the form (T1, ..., Tn) => U, which is a shorthand for the trait FunctionN in the standard library.

A Method Type is a non-value type. That means there is no value - no object, no instance - with a method type... A method type is a def declaration - everything about a def except its body.

You can't directly assign a method do a val:

def foo(x: Int) = x
val myFooVal = foo //does not compile   

The process of eta-expansion can convert a method to a function, which you can assign to a val:

val myFooVal = foo _

Here is a blog post that explores eta-expansion a little bit more in depth.

The interesting thing in your example is that you're mixing methods with functions. This is totally fine, but it might be a part of what's confusing you here:

def add(x:Int) = (y:Int) => x + (-y)

This is method that returns a function, while this:

def add2(x:Int)(y:Int) =  x + y

Is a pure method, which, as with all methods, can be converted to a function type using eta-expansion:

add2 _ //Int => (Int => Int)
add2(2) _ //Int => Int

It might be edifying to play around in the REPL to see how Scala treats these types differently:

def add(x:Int) = (y:Int) => x + (-y)
//add: (x: Int)Int => Int

def add2(x:Int)(y:Int) =  x + y
//add2: (x: Int)(y: Int)Int

Notice how the printout from the REPL differs here. In the first example, we can see that add is a method that returns something of type Int => Int, which is a function. In the second example, the method syntax is preserved through the second argument.

Community
  • 1
  • 1
Ben Reich
  • 16,222
  • 2
  • 38
  • 59