Ignacio Alorre
Ignacio Alorre

Reputation: 7605

Scala - Two functions sharing the second parameter list

I am new in Scala and I just came across a situation that I would like someone could explain me.

When watching a Martin Odersky's course I found the following script he uses to explain functions which return a function

val tolerance = 0.0001 

def isCloseEnough(x : Double, y : Double) = abs((x - y)/ x) / x < tolerance  

def fixedPoint(f : Double => Double)(firstGuess: Double) = {
    def iterate(guess: Double): Double = {
        val next = f(guess)
        if(isCloseEnough(guess,next))next
        else iterate(next)
    }
        iterate(firstGuess)
  }                                              

fixedPoint(x => 1 + x/2)(1)    

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

def sqrt(x : Double) = fixedPoint(averageDamp(y => x/y))(1)


sqrt(2) 

I understand perfectly how the scrip works, but I didn't expect this line:

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

I know that thanks to Currying, Scala let us write functions with several parameter list. So the call to fixedPoint passing as parameter the result of avergaDamp and (1) is clear for me.

What I don't understand is how averageDamp uses the second parameter list of fixedPoint when it itself is inside the first parameter list. I though that would be a different scope, so I was expecting something like:

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

What is the property of Scala which allow us to implement the currying in this way? Is something similar to an implicit applied to a parameter list?

Thanks for your time

Upvotes: 1

Views: 107

Answers (2)

Shashank
Shashank

Reputation: 370

This line works because in the following expression:

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

function "averageDamp(y => x/y)" is "passed by name" i.e. it will not be evaluated while passing to function "fixedPoint" but will be evaluated when it is called from inside "fixedPoint".

value "(1)" is just pass to argument "firstGuess" of "fixedPoint" which will be supplied to parameter "guess" inside the function definition in following expression:

val next = f(guess)

Upvotes: 2

Alexey Romanov
Alexey Romanov

Reputation: 170713

This is just how multiple parameter lists work: averageDamp(y => x/y) is equivalent to z => averageDamp(y => x/y)(z) and so its type is Double => Double.

If you wrote fixedPoint(averageDamp(y => x/y)(1))(1) as you expect, it would have a type mismatch because averageDamp(y => x/y)(1) has type Double and fixedPoint needs Double => Double.

Implicits aren't relevant here.

Upvotes: 2

Related Questions