I have several questions related curried function. Here I ask them one-by-one
1) http://twitter.github.com/scala_school/basics.html gives an example of curried function -- I thought it's a function definition, but actually it's not. The REPL does not recognize this as a valid statement at all.
multiplyThenFilter { m: Int => m * 2 } { n: Int => n < 5}
2) Why can't we define a function from partially parameterized method? i.e., what's wrong with the following definition?
scala> def multiply(m: Int, n: Int): Int = m * n
multiply: (m: Int, n: Int)Int
scala> val timesTwo = multiply(2,_)
<console>:11: error: missing parameter type for expanded function ((x$1) => multiply(2, x$1))
val timesTwo = multiply(2,_)
^
3) Why can't we make a partially parameterized function curried? i.e., what's wrong with the following definition?
scala> (multiply(_,_)).curried
res13: Int => (Int => Int) = <function1> // THIS IS OK
scala> (multiply(20,_)).curried
<console>:12: error: missing parameter type for expanded function ((x$1) => multiply(20, x$1))
(multiply(20,_)).curried
^
Currying is the process of converting a function with multiple arguments into a sequence of functions that take one argument. Each function returns another function that consumes the following argument.
Curried functions are also an important application of closure. They split a function with many parameters into functions with only one parameter each. The context between function calls is saved thanks to closures (outer-inner pattern).
Currying is when you break down a function that takes multiple arguments into a series of functions that each take only one argument. Here's an example in JavaScript: function add (a, b) { return a + b; } add(3, 4); // returns 7. This is a function that takes two arguments, a and b, and returns their sum.
Now, currying a function is forcing it to take a single parameter at a time. So rather than calling it like distance( start, end ) , we would call it like this: distance(start)(end) . Each parameter is passed in individually, and each function call returns another function, until all parameters have been provided.
The Scala School example is confusing—it's definitely not a definition. There's an issue open for it on GitHub, so maybe it's a bug. You can imagine a reasonable definition might look like this:
def multiplyThenFilter(f: Int => Int)(p: Int => Boolean): Int => Option[Int] = {
i =>
val j = f(i)
if (p(j)) Some(j) else None
}
(Or, equivalently, f andThen (Some(_) filter p)
.)
Then the example would be a function that doubles its input and returns the result in a Some
if it's less than 5, and a None
otherwise. But nobody knows exactly what the author intended until there's a response to that issue.
The reason that your timesTwo
doesn't work is just that the Scala compiler doesn't support that kind of type inference—see this question and my answer there for a bit of related detail. You'll need to go with one of the following:
def multiply(m: Int, n: Int): Int = m * n
val timesTwo = multiply(2, _: Int)
def multiply(m: Int)(n: Int): Int = m * n
val timesTwo = multiply(2) _
I.e., if you want type inference here you'll need to use multiple parameter lists. Otherwise you have to help the compiler out with the type.
For your third question, assume we've got the following to avoid the issue in your second question:
val timesTwo = multiply(2, _: Int)
This is a Function1
, which just doesn't have a curried
method—you need a Function2
(or Function3
, etc.) for that.
It just doesn't make sense to talk about currying a function with a single argument. Currying takes a function with multiple arguments and gives you a function taking a single argument that returns another function (which itself possibly takes a single argument and returns another function, etc.).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With