This is an excerpt from the 1st Edition of the Scala Cookbook (partially modified for the internet). This is Recipe 9.9, “A real-world functional programming example in Scala.”
Problem
Understanding functional programming concepts is one thing; putting them into practice in a real project is another. You’d like to see a real example of functional programming in Scala.
Solution
To demonstrate some of the functional programming (FP) techniques that I introduced earlier in this chapter, the following example shows one way to implement Newton’s Method, a mathematical method that can be used to solve the roots of equations.
As you can see from the code, the method named newtonsMethod
takes functions as its first two parameters. It also takes two other Double
parameters, and returns a Double
. The two functions that are passed in should be the original equation (fx
) and the derivative of that equation (fxPrime
).
The method newtonsMethodHelper
also takes two functions as parameters, so you can see how the functions are passed from newtonsMethod
to newtonsMethodHelper
. Here is the complete source code for this example:
object NewtonsMethod { def main(args: Array[String]) { driver } /** * A "driver" function to test Newton's method. * Start with (a) the desired f(x) and f'(x) equations, * (b) an initial guess and (c) tolerance values. */ def driver { // the f(x) and f'(x) functions val fx = (x: Double) => 3*x + math.sin(x) - math.pow(math.E, x) val fxPrime = (x: Double) => 3 + math.cos(x) - math.pow(Math.E, x) val initialGuess = 0.0 val tolerance = 0.00005 // pass f(x) and f'(x) to the Newton's Method function, along with // the initial guess and tolerance val answer = newtonsMethod(fx, fxPrime, initialGuess, tolerance) println(answer) } /** * Newton's Method for solving equations. * @todo check that |f(xNext)| is greater than a second tolerance value * @todo check that f'(x) != 0 */ def newtonsMethod(fx: Double => Double, fxPrime: Double => Double, x: Double, tolerance: Double): Double = { var x1 = x var xNext = newtonsMethodHelper(fx, fxPrime, x1) while (math.abs(xNext - x1) > tolerance) { x1 = xNext println(xNext) // debugging (intermediate values) xNext = newtonsMethodHelper(fx, fxPrime, x1) } xNext } /** * This is the "x2 = x1 - f(x1)/f'(x1)" calculation */ def newtonsMethodHelper(fx: Double => Double, fxPrime: Double => Double, x: Double): Double = { x - fx(x) / fxPrime(x) } }
Discussion
As you can see, a majority of this code involves defining functions, passing those functions to methods, and then invoking the functions from within a method.
The method name newtonsMethod
will work for any two functions fx
and fxPrime
, where fxPrime
is the derivative of fx
(within the limits of the “to do” items that are not implemented).
To experiment with this example, try changing the functions fx
and fxPrime
, or implement the @todo
items in newtonsMethod
.
The algorithm shown comes from an old textbook titled Applied Numerical Analysis, by Gerald and Wheatley, where the approach was demonstrated in pseudocode.
this post is sponsored by my books: | |||
#1 New Release |
FP Best Seller |
Learn Scala 3 |
Learn FP Fast |