Skip to content

Instantly share code, notes, and snippets.

@johnnymo87
Created May 17, 2014 17:38
Show Gist options
  • Save johnnymo87/711e1d38e2e5707fda06 to your computer and use it in GitHub Desktop.
Save johnnymo87/711e1d38e2e5707fda06 to your computer and use it in GitHub Desktop.
Finding fixed points
import math.abs
object finding_fixed_points {
val tolerance = 0.0001 //> tolerance : Double = 1.0E-4
def isCloseEnough(x: Double, y: Double) =
abs((x - y) / x) / x < tolerance //> isCloseEnough: (x: Double, y: Double)Boolean
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: (f: Double => Double)(firstGuess: Double)Double
fixedPoint(x => 1 + x/2)(1) //> res0: Double = 1.999755859375
def averageDamp(f: Double => Double)(x: Double) = (x + f(x))/2
//> averageDamp: (f: Double => Double)(x: Double)Double
def sqrt(x: Double) =
fixedPoint(averageDamp(y => x / y))(1) //> sqrt: (x: Double)Double
sqrt(2) //> res1: Double = 1.4142135623746899
}
@johnnymo87
Copy link
Author

The code above is from lecture 2.3 of Functional Programming Principles in Scala.

It blows my mind how composable functions are in Scala.

If I call averageDamp with two arguments, I get the expected return value -- a Double. But if I call it with only one argument (a function), I get back averageDamp's body mixed with that function. I can then use that to my advantage, injecting that combination of functions into my use of the fixedPoint function in sqrt. (I needed this "average damping" functionality when implementing sqrt with fixedPoint because otherwise it would never converge, thrashing forever between 1 and 2.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment