please find below a piece of code from Coursera online course (lecture 2.3) on functional programming in Scala.
package week2
import math.abs
object lecture2_3_next {
def fixedPoint(f: Double => Double)(firstGuess: Double): Double = {
val tolerance = 0.0001
def isCloseEnough(x: Double, y: Double): Boolean = abs((x - y) / x) / x < tolerance
def iterate(guess: Double): Double = {
val next = f(guess)
if (isCloseEnough(guess, next)) next
else iterate(next)
}
iterate(firstGuess)
}
def averageDamp(f: Double => Double)(x: Double): Double = (x + f(x)) / 2
def sqrt(x: Double): Double = fixedPoint(averageDamp(y => x / y))(1)
sqrt(2)
}
A few points blocked me while I'm trying to understand this piece of code.
I'd like your help to understanding this code.
The 2 points that annoying me are :
- when you call averageDamp, there are 2 parameters 'x' and 'y' in the function passed (eg. averageDamp(y => x / y)) but you never specify the 'y' parameter in the definition of the averageDamp function (eg. def averageDamp(f: Double => Double)(x: Double): Double = (x + f(x)) / 2). Where and how do the scala compiler evaluate the 'y' parameter.
- second point may be related to the first, I don't know in fact. When I call the averageDamp function, I pass only the function 'f' parameter (eg. y => x / y) but I don't pass the second parameter of the function which is 'x' (eg. (x: Double) second parameter). How the scala compiler is evaluating the 'x' parameter in this case to render the result of the averageDamp call.
I think I missed something about the evaluation or substitution model of scala and functional programming.
Thank's for your help and happy new year !
Hervé
1) You don't pass an x and an y parameter as f, you pass a function. The function is defined as y => x / y, where y is just a placeholder for the argument of this function, while x is a fixed value in this context, as it is given as argument for the sqrt method (in the example x is 2). Instead of the fancy lambda-syntax, you could write as well
def sqrt(x: Double): Double = fixedPoint(averageDamp(
new Function1[Double,Double] {
def apply(y:Double):Double = x / y
}
))(1)
Nothing magic about this, just an abbreviation.
2) When you have a second parameter list, and don't use it when calling the method, you do something called "currying", and you get back a partial function. Consider
def add(x:Int)(y:Int) = x + y
If you call it as add(2)(3), everything is "normal", and you get back 5. But if you call add(2), the second argument is still "missing", and you get back a function expecting this missing second argument, so you have something like y => 2 + y
The x is not a parameter of the (anonymous) function, it is a parameter of the function sqrt. For the anonymous function it is a bound closure.
To make it more obvious, let's rewrite it and use a named instead of an anonymous function:
def sqrt(x: Double): Double = fixedPoint(averageDamp(y => x / y))(1)
will can be rewritten as this:
def sqrt(x: Double): Double = {
def funcForSqrt(y: Double) : Double = x / y // Note that x is not a parameter of funcForSqrt
// Use the function fundForSqrt as a parameter of averageDamp
fixedPoint(averageDamp(funcForSqrt))(1)
}
Related
I have two functions
val mul3 = 3*(_: Double)
val pow2 = (x: Double) => x*x
What I don't understand how it works at all is this:
println((pow2.andThen[Double] _ )(mul3)(5))
1) I thought andThen operates with results of the function to the left, but here it is [Double] _ - what is this? (I was expecting something like pow2 andThen mul3)
2) Why is mul3 passed to pow2 if pow2 expects Double? (mul3(pow2) gives an error)
3) What is being passed to pow2? Is it mul3 or 15?
4) What does . mean?
scala fiddle
Lets go step by step.
val mul3 = 3*(_: Double)
Is a Function from a Double to another Double. Thus, is type is Function1[Double, Double].
The same applies to:
val pow2 = (x: Double) => x*x
Now, remember that in Scala, everything is an object. And that there are not operators, only methods. So:
pow2.andThen[Double]
Is calling the andThen on method on the Function1 class.
As you can see on the scaldoc, that method receives another function. Also, it is parametric in the return type of the second function, which determines the return type of the composed function that is returned.
So the [Double] part is just specifying that type.
pow2.andThen[Double] _
Is using the underscore syntax to create another function.
The above line is equivalent to:
f => pow2.andThen[Double](f)
So, it is creating a function that takes another function as input, and returns another function. The resulting function will call pow2 first and then call the function passed as the argument.
Thus, it is of type Function1[Function1[Double, Double], Function[Double, Double]].
Then
(pow2.andThen[Double] _ )(mul3)
Is passing mul3 as the argument of that function, returning a final function (Function1[Double, Doule]) that calls pow2 first and pass the result to mul3.
Finally
(pow2.andThen[Double] _ )(mul3)(5)
Is calling the resulting function with 5 as is input.
After substitution, the code is equivalent to:
x => mul3(pow2(x))
x => 3 * (x * x)
5 => 3 * (x * x)
3 * (5 * 5)
75.0
Side note, IMHO, that code is very cryptic and far for what I would call idiomatic in Scala.
Hi I'm newbie in scala.
when I write the below code, Even I didn't declared variable y, but it is allowed.
object exercise {
def fixedPoint(f: Double => Double)(firstGuess: Double) = {
//some code
}
def sqrt(x: Double) = fixedPoint(y => x / y)(1) //No error. weird...
}
I don't understand how does it works?
I didn't declared variable y
Actually, you did.
This ...
y => ...
... translates into, "Here's a function that takes a single argument. I'm going to call that argument y."
When you declare f: Double => Double, it means that function f will take Double as input parameter and will return Double as output. So, when you pass y => x / y function, y here is of type Double and x/y(output) is of type double.
It is not giving any compiler error because compiler can infer the type based on type of function fixedPoint expects.
Suggest you have a look for How to use function literals (anonymous functions) in Scala.
In the post, it use a simple example (i: Int) => i % 2 == 0 to act as a function literals, and pass it to the function filter. And see follows:
Because the Scala compiler can infer from the expression that i is an Int, the Int declaration can be dropped off: val evens = x.filter(i => i % 2 == 0)
Then, this is exactly the situation in your post for y => x / y, the Double was dropped off in your code as scala compiler can infer from the expression.
Before I answer this question let me modify your code as:
object exercise {
def fixedPoint(f: Double => Double)(firstGuess: Double) = {
f(firstGuess) //call the function in f with the curried parameter
}
def sqrt(x: Double) = fixedPoint(y => x / y)(1) //No error. weird...
}
I have added a line to call function f (which takes Double and returns Double) with firstGuess parameter.
f(firstGuess) //call the function in f with the curried parameter
Let's see what what sqrt function is all about
def sqrt(x: Double) = fixedPoint(y => x / y)(1)
It takes a x and invokes fixedPoint with y => x/y and 1
now your y is firstGuess parameter (as per modified code) and x is the sqrt parameter.
The following code works but I don't quite understand how the arguments are mapped to the parameter lists. Please be aware Im new to Scala.
import Math.abs
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)
}
def averageDamp(f: Double => Double)(x: Double) = (x + f(x)) / 2
def sqrt(x: Double) =
fixedPoint(averageDamp(y => x / y))(1.0)
sqrt(2.0)
The body of the sqrt function above is fixedPoint(averageDamp(y => x / y))(1.0)
where
(y => x / y) maps to (f: Double => Double) of the averageDamp function and
(1.0) maps to (firstGuess: Double) of the fixedPoint function but
looks like nothing maps to (x: Double) of the averageDamp function.
Thank you in advance.
This is called currying. What's really happening is that averageDamp(y => x / y) is being interpreted as a function: Double => Double, because once you set the first parameter list to a particular set of values, you obtain a function that takes the second parameter list.
For example, consider the following code:
def multiply(x: Double)(y: Double) = x * y
val multiplyByFive: Double => Double = multiply(5)
println(multiplyByFive(2)) // 10
println(multiplyByFive(6)) // 30
As you see, the fact of applying multiply with only one parameter list out of two creates a new function of the second parameter list (here (y: Double)) that has a fixed set of values for the first parameter list (here (5)).
Another equivalent way to write this, which perhaps will be more explicit for you, is the following :
val multiplyByFive: Double => Double = multiply(5)(_)
Here we explicitly apply the function with two parameters lists, but using a wildcard for the second, which is a way to tell to the compiler to create a function that replaces the underscore by a parameter of the function.
I am going through lectures from excellent Martin Odersky's FP course and one of the lectures demonstrates higher-order functions through Newton's method for finding fixed points of certain functions. There is a cruicial step in the lecture where I think type signature is being violated so I would ask for an explanation. (Apologies for the long intro that's inbound - it felt it was needed.)
One way of implementing such an algorithm is given like this:
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)
}
Next, we try to compute the square root via fixedPoint function, but the naive attempt through
def sqrt(x: Double) = fixedPoint(y => x / y)(1)
is foiled because such an approach oscillates (so, for sqrt(2), the result would alternate indefinitely between 1.0 and 2.0).
To deal with that, we introduce average damping, so that essentially we compute the mean of two nearest calculated values and converge to solution, therefore
def sqrt(x: Double) = fixedPoint(y => (y + x / y) / 2)(1)
Finally, we introduce averageDamp function and the task is to write sqrt with fixedPoint and averageDamp. The averageDamp is defined as follows:
def averageDamp(f: Double => Double)(x: Double) = (x + f(x)) / 2
Here comes the part I don't understand - my initial solution was this:
def sqrt(x: Double) = fixedPoint(z => averageDamp(y => x / y)(z))(1)
but prof. Odersky's solution was more concise:
def sqrt(x: Double) = fixedPoint(averageDamp(y => x / y))(1)
My question is - why does it work? According to function signature, the fixedPoint function is supposed to take a function (Double => Double) but it doesn't mind being passed an ordinary Double (which is what averageDamp returns - in fact, if you try to explicitly specify the return type of Double to averageDamp, the compiler won't throw an error).
I think that my approach follows types correctly - so what am I missing here? Where is it specified or implied(?) that averageDamp returns a function, especially given the right-hand side is clearly returning a scalar? How can you pass a scalar to a function that clearly expects functions only? How do you reason about code that seems to not honour type signatures?
Your solution is correct, but it can be more concise.
Let's scrutinize the averageDamp function more closely.
def averageDamp(f: Double => Double)(x: Double): Double = (x + f(x)) / 2
The return type annotation is added to make it more clearly. I think what you are missing is here:
but it doesn't mind being passed an ordinary Double (which is what averageDamp returns - in fact, if you try to explicitly specify the
return type of Double to averageDamp, the compiler won't throw an
error).
But averageDamp(y => y/x) does return a Double => Double function! averageDamp requires to be passed TWO argument lists to return a Double.
If the function receive just one argument, it still wants the other one to be completed. So rather than returning the result immediately, it returns a function, saying that "I still need an argument here, feed me that so I will return what you want".
Prof MO did pass ONE function argument to it, not two, so averageDamp is partially applied, in the sense that it returns a Double => Double function.
The course will also tell you functions with multiple argument lists are syntactical sugar form of this:
def f(arg1)(arg2)(arg3)...(argN-1)(argN) = (argN) => f(arg1)(arg2)(arg3)...(argN-1)
If you give one less argument than f needs, it just return the right side of equation, that is, a function. So, heeding that averageDamp(y => x / y), the argument passed to fixPoint, is actually a function should help you understand the question.
Notice: There is some difference between partially applied function(or function currying) and multiple argument list function
For example you cannot declare like this
val a = averageDamp(y => y/2)
The compiler will complain about this as 'method is not a partially applied function'.
The difference is explained here: What's the difference between multiple parameters lists and multiple parameters per list in Scala?.
Multiple parameter lists are syntactic sugar for a function that returns another function. You can see this in the scala shell:
scala> :t averageDamp _
(Double => Double) => (Double => Double)
We can write the same function without the syntactic sugar - this is the way we'd do it in e.g. Python:
def averageDamp(f: Double => Double): (Double => Double) = {
def g(x: Double): Double = (x + f(x)) / 2
g
}
Returning a function can look a bit weird to start with, but it's complementary to passing a function as an argument and enables some very powerful programming techniques. Functions are just another type of value, like Int or String.
In your original solution you were reusing the variable name y, which I think makes it slightly confusing; we can translate what you've written into:
def sqrt(x: Double) = fixedPoint(z => averageDamp(y => x / y)(z))(1)
With this form, you can hopefully see the pattern:
def sqrt(x: Double) = fixedPoint(z => something(z))(1)
And hopefully it's now obvious that this is the same as:
def sqrt(x: Double) = fixedPoint(something)(1)
which is Odersky's version.
Let me clarify my question by example. This is a standard exponentiation algorithm written with tail recursion in Scala:
def power(x: Double, y: Int): Double = {
def sqr(z: Double): Double = z * z
def loop(xx: Double, yy: Int): Double =
if (yy == 0) xx
else if (yy % 2 == 0) sqr(loop(xx, yy / 2))
else loop(xx * x, yy - 1)
loop(1.0, y)
}
Here sqr method is used to produce the square of loop's result. It doesn't look like a good idea - to define a special function for such a simple operation. But, we can't write just loop(..) * loop(..) instead, since it doubles the calculations.
We also can write it with val and without sqr function:
def power(x: Double, y: Int): Double = {
def loop(xx: Double, yy: Int): Double =
if (yy == 0) xx
else if (yy % 2 == 0) { val s = loop(xx, yy / 2); s * s }
else loop(xx * x, yy - 1)
loop(1.0, y)
}
I can't say that it looks better then variant with sqr, since it uses state variable. The first case is more functional the second way is more Scala-friendly.
Anyway, my question is how to deal with cases when you need to postprocess function's result? Maybe Scala has some other ways to achieve that?
You are using the law that
x^(2n) = x^n * x^n
But this is the same as
x^n * x^n = (x*x)^n
Hence, to avoid squaring after recursion, the value in the case where y is even should be like displayed below in the code listing.
This way, tail-calling will be possible. Here is the full code (not knowing Scala, I hope I get the syntax right by analogy):
def power(x: Double, y: Int): Double = {
def loop(xx: Double, acc: Double, yy: Int): Double =
if (yy == 0) acc
else if (yy % 2 == 0) loop(xx*xx, acc, yy / 2)
else loop(xx, acc * xx, yy - 1)
loop(x, 1.0, y)
}
Here it is in a Haskell like language:
power2 x n = loop x 1 n
where
loop x a 0 = a
loop x a n = if odd n then loop x (a*x) (n-1)
else loop (x*x) a (n `quot` 2)
You could use a "forward pipe". I've got this idea from here: Cache an intermediate variable in an one-liner.
So
val s = loop(xx, yy / 2); s * s
could be rewritten to
loop(xx, yy / 2) |> (s => s * s)
using an implicit conversion like this
implicit class PipedObject[A](value: A) {
def |>[B](f: A => B): B = f(value)
}
As Petr has pointed out: Using an implicit value class
object PipedObjectContainer {
implicit class PipedObject[A](val value: A) extends AnyVal {
def |>[B](f: A => B): B = f(value)
}
}
to be used like this
import PipedObjectContainer._
loop(xx, yy / 2) |> (s => s * s)
is better, since it does not need a temporary instance (requires Scala >= 2.10).
In my comment I pointed out that your implementations can't be tail call optimised, because in the case where yy % 2 == 0, there is a recursive call that is not in tail position. So, for a large input, this can overflow the stack.
A general solution to this is to trampoline your function, replacing recursive calls with data which can be mapped over with "post-processing" such as sqr. The result is then computed by an interpreter, which steps through the return values, storing them on the heap rather than the stack.
The Scalaz library provides an implementation of the data types and interpreter.
import scalaz.Free.Trampoline, scalaz.Trampoline._
def sqr(z: Double): Double = z * z
def power(x: Double, y: Int): Double = {
def loop(xx: Double, yy: Int): Trampoline[Double] =
if (yy == 0)
done(xx)
else if (yy % 2 == 0)
suspend(loop(xx, yy / 2)) map sqr
else
suspend(loop(xx * x, yy - 1))
loop(1.0, y).run
}
There is a considerable performance hit for doing this, though. In this particular case, I would use Igno's solution to avoid the need to call sqr at all. But, the technique described above can be useful when you can't make such optimisations to your algorithm.
In this particular case
No need for utility functions
No need for obtuse piping / implicits
Only need a single standalone recursive call at end - to always give tail recursion
def power(x: Double, y: Int): Double =
if (y == 0) x
else {
val evenPower = y % 2 == 0
power(if (evenPower) x * x else x, if (evenPower) y / 2 else y - 1)
}