 Image source

While going through lexical scoping concept in LISP; I wondered whether such support is available in Swift or not. And it does. Yay…

I took a simple function — ‘square root of a number’ to try out the lexical scoping. I used Newton’s method for calculating square roots. Below is the first version.

sqRt is a recursive function. The code terminates when the guess made in earlier step is good enough. Else guess is improved and function is called again.

 `````` 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 `````` ``````func square(_ x: Double) -> Double { return x * x } func avg(_ x: Double, _ y: Double) -> Double { return (x + y) / 2 } func goodEnough(x: Double, guess: Double) -> Bool { return abs(square(guess) - x) < 0.001 } func improveGuess(x: Double, guess: Double) -> Double { return avg((x / guess), guess) } func sqRt(x: Double, guess: Double) -> Double { if goodEnough(x: x, guess: guess) { return guess } return sqRt(x: x, guess: improveGuess(x: x, guess: guess)) } sqRt(x: 2, guess: 1) sqRt(x: 9, guess: 1) sqRt(x: 16, guess: 2)``````

But then functions like goodEnough and improveGuess does not make any sense outside squareRoot function scope. Thankfully in Swift, functions are first class citizens. We can declare function just like declaring variable. This brings me to the second version of sqRt function.

 `````` 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 `````` ``````func sqRt(x: Double, guess: Double) -> Double { let square = { (x: Double) in return x * x } let avg = { (x: Double, y: Double) in return (x + y) / 2 } func goodEnough(x: Double, guess: Double) -> Bool { return abs(square(guess) - x) < 0.001 } func improveGuess(x: Double, guess: Double) -> Double { return avg((x / guess), guess) } if goodEnough(x: x, guess: guess) { return guess } return sqRt(x: x, guess: improveGuess(x: x, guess: guess)) } sqRt(x: 2, guess: 1) sqRt(x: 9, guess: 1) sqRt(x: 16, guess: 2)``````

Functions like improveGuess, goodEnough are operating on the function parameters of sqRt. As these functions are already in the scope of sqRt function, one can argue that passing parameters to these inner functions is redundant. Which is indeed true and that’s what is addressed with lexical scoping. Parameters/ variables of the enclosing function are in scope for these functions.

A language supporting LexicalScoping has following characteristics:

• Functions (and procedures, etc.) can be defined within other functions
• Such inner functions have access to the local variables defined in the enclosing scope.
• These inner functions also have an access to the function parameters of the enclosing function.
Version 3 of the sqRt function by leveraging lexical scoping support is as follows.

 `````` 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 `````` ``````func sqRt(x: Double, guess: Double) -> Double { let square = { () in return guess * guess } let avg = { (y: Double) in return (guess + y) / 2 } func goodEnough() -> Bool { return abs(square() - x) < 0.001 } func improveGuess() -> Double { return avg(x / guess) } return goodEnough() ? guess : sqRt(x: x, guess: improveGuess()) } sqRt(x: 2, guess: 1) sqRt(x: 9, guess: 1) sqRt(x: 16, guess: 2)``````

Hey wait! Why can’t we leverage Swift’s support further to concise the code. Square, goodEnough and improveGuess look like variables. So let’s simplify those.

 `````` 1 2 3 4 5 6 7 8 9 10 11 `````` ``````func sqRt(x: Double, guess: Double) -> Double { let guessSquare = guess * guess let guessGoodEnough = abs(guessSquare - x) < 0.001 let avg = { (y: Double) in return (guess + y) / 2 } let improvedGuess = avg(x / guess) return guessGoodEnough ? guess : sqRt(x: x, guess: improvedGuess) } sqRt(x: 2, guess: 1) sqRt(x: 9, guess: 1) sqRt(x: 16, guess: 2)``````

I hope you understood lexical scoping support in Swift. Let me know your thoughts on this.

This blog is originally published here.