user1974753
user1974753

Reputation: 1457

Calling curried functions in Scala?

So I am a bit confused as to how curried functions in Scala work. I have the following code which compiles, but I am not sure how!

def fixedPoint(f: Double => Double, initialGuess: Double) = {
   //dummy impl, does nothing.
}

def averageDamp(f: Double => Double)(x: Double) = (x + f(x))/2

def sqrt(x: Int) = {
  fixedPoint(averageDamp(y => x/y))(1)
}

This code compiles fine, but I would have thought averageDamp needs to also take another parameter? So it should be :

fixedPoint(averageDamp(y=> x/y)(1))(1)

But this does not compile, and i get a message saying type mismatch; found : Double required: Double ⇒ Double

The following does not compile, which makes sense:

val num = averageDamp(y => x/y)

This gives the compile error message : "missing argument list for method averageDamp in object Foo Unapplied methods are only converted to functions when a function type is expected."

So I am not sure why it compiles when calling averageDamp with one parameter inside the call to fixedPoint, but fails to compile when i call it on its own.

Any help would be great.

Upvotes: 3

Views: 4329

Answers (1)

Łukasz
Łukasz

Reputation: 8663

This is the code that compiles

def fixedPoint(f: Double => Double, initialGuess: Double) = {
   //dummy impl, does nothing.
}

def averageDamp(f: Double => Double)(x: Double) = (x + f(x))/2

def sqrt(x: Int) = {
  fixedPoint(averageDamp(y => x/y), 1)
}

At this line

fixedPoint(averageDamp(y => x/y), 1)

even though averageDamp needs one more parameter list (that has one more parameter) it is valid not to put it. Actually this is the reason why it was defined as curried in the first place - so that you can use it as a function.

scala>     val num = averageDamp(y => 5/y)(1)
num: Double = 3.0

would give you a result of type Double as you probably expect.

If you don't pass the second parameter list you can receive a function

val fun = averageDamp(y => 5/y)

gives you an error tries to tell you that you need to inform compiler that you want fun to be a function. You can do this in following ways:

scala>     val fun: Double => Double = averageDamp(y => 5/y)
fun: Double => Double = <function1>
scala>     val fun = averageDamp(y => 5/y) _
fun: Double => Double = <function1>

Now look at fixedPoint

def fixedPoint(f: Double => Double, initialGuess: Double)

it expects a function Double => Double so we can pass it

fixedPoint(averageDamp(y => 5/y), 1)

compiler knows that first parameter should be a function and with this knowledge it converts this method to a function that has yet to take that x: Double parameter and will return (x + f(x))/2

Upvotes: 7

Related Questions