sol4me
sol4me

Reputation: 15698

Scala currying with function argument

I am learning currying in scala and trying to apply my knowledge on the following piece of code.

object excercise {

  def sqrt2(input : Double) : ((Double, Double) => Double, Double) => Double = {
    def iter(guessFxn : (Double, Double) => Double, initial : Double) : Double = {
      if (isGoodEnough(initial)) initial
      else {
        val newGuess: Double = guessFxn(initial, input)
        iter(guessFxn, newGuess)
      }
    }

    iter

    def isGoodEnough(guess: Double): Boolean = {
      math.abs(guess * guess - input ) / input < 0.001
    }

  }
  println(sqrt2(2) ( (g: Double, c: Double) => (g + c / g) / 2, 1))

}

What i want to achieve is that sqrt2 should return a function which takes as 2 arguments
1. fxn(that takes 2 doubles as arg and return a double val)
2. double val

When i am trying to run the worksheet it is giving me error

Error: missing arguments for method iter;
follow this method with `_' if you want to treat it as a partially applied function
    iter
    ^
Error: type mismatch;
 found   : Unit
 required: ((Double, Double) => Double, Double) => Double
  }
  ^
Error: missing arguments for method iter;
follow this method with `_' if you want to treat it as a partially applied function
    iter
    ^

Upvotes: 1

Views: 420

Answers (1)

Mik378
Mik378

Reputation: 22171

You just have to inverse the order of those piece of codes:

iter

def isGoodEnough(guess: Double): Boolean = {
   math.abs(guess * guess - input ) / input < 0.001
}

becomes:

def isGoodEnough(guess: Double): Boolean = {
   math.abs(guess * guess - input ) / input < 0.001
}

iter 

Indeed, ending with an inner declared method involves a return type of Unit...that's not what you want.

Besides, you had this advice:

follow this method with `_' if you want to treat it as a partially applied function
    iter

because as explains before, iter method is not returned (since its call is not made at the end of the method) and thus compiler expects it to be executed.
Of course, to be executed, it needs its compulsory parameters, that you didn't provide.
So the compiler "thinks" that you expected to partially apply the function but badly. Note than a partially applied function is not the same concept than a partial function, that has a different meaning ... ).
It would allow to defer the call, and it's mostly used when dealing standard function (not curried), where we might need to provide only the first parameter and later the following.

Example of partially applied function:

def sum(i: Int, j: Int){...}

calls:

sum 1 _ //just the second parameter needs to be applied later.
sum _  //none parameter is specified, would need to specify both later.
sum 1 2 //complete call, not partially applied so

You can find a good use case of partially applied function here.

Upvotes: 3

Related Questions