Sorry for the newbie question. I realize that there are several questions on here about what currying and partially applied functions are, but I'm asking about how they are different. As a simple example, here is a curried function for finding even numbers:
def filter(xs: List[Int], p: Int => Boolean): List[Int] =
if (xs.isEmpty) xs
else if (p(xs.head)) xs.head :: filter(xs.tail, p)
else filter(xs.tail, p)
def modN(n: Int)(x: Int) = ((x % n) == 0)
val nums = List(1,2,3,4,5,6,7,8)
def modN(n: Int, x: Int) = ((x % n) == 0)
val p = modN(2, _: Int)
The semantic difference has been explained fairly well in the answer linked to by Plasty Grove.
In terms of functionality, there doesn't seem much of a difference, though. Let's look at some examples to verify that. First, a normal function:
scala> def modN(n: Int, x: Int) = ((x % n) == 0) scala> modN(5, _ : Int) res0: Int => Boolean = <function1>
So we get a partially applied
<function1> that takes an
Int, because we've already given it the first integer. So far so good. Now to currying:
scala> def modNCurried(n: Int)(x: Int) = ((x % n) == 0)
With this notation, you'd naively expect the following to work:
scala> modNCurried(5) <console>:9: error: missing arguments for method modN; follow this method with `_' if you want to treat it as a partially applied function modNCurried(5)
So the multiple parameter list notation doesn't really seem to create a curried function right away (assumingly to avoid unnecessary overhead) but waits for you to explicitly state that you want it curried (the notation has some other advantages as well):
scala> modNCurried(5) _ res24: Int => Boolean = <function1>
Which is exactly the same thing we got before, so no difference here, except for notation. Another example:
scala> modN _ res35: (Int, Int) => Boolean = <function2> scala> modNCurried _ res36: Int => (Int => Boolean) = <function1>
This demonstrates how partially applying a "normal" function results in a function that takes all parameters, whereas partially applying a function with multiple parameter lists creates a chain of functions, one per parameter list which, all return a new function:
scala> def foo(a:Int, b:Int)(x:Int)(y:Int) = a * b + x - y scala> foo _ res42: (Int, Int) => Int => (Int => Int) = <function2> scala> res42(5) <console>:10: error: not enough arguments for method apply: (v1: Int, v2: Int)Int => (Int => Int) in trait Function2. Unspecified value parameter v2.
As you can see, because the first parameter list of
foo has two parameters, the first function in the curried chain has two parameters.
In summary, partially applied functions aren't really different form curried functions in terms of functionality. This is easily verified given that you can convert any function to a curried one:
scala> (modN _).curried res45: Int => (Int => Boolean) = <function1 scala> modNCurried _ res46: Int => (Int => Boolean) = <function1>
Note: The reason that your example
println(filter(nums, modN(2)) works without the underscore after
modN(2) seems to be that the Scala compiler simply assumes that underscore as a convenience for the programmer.
Addition: As @asflierl has correctly pointed out, Scala doesn't seem to be able to infer the type when partially applying "normal" functions:
scala> modN(5, _) <console>:9: error: missing parameter type for expanded function ((x$1) => modN(5, x$1))
Whereas that information is available for functions written using multiple parameter list notation:
scala> modNCurried(5) _ res3: Int => Boolean = <function1>
This answers shows how this can be very useful.