Functional Programming Principles in Scala¶
Week 1¶
-
Theory wise, pure imperative programming languages is limited by "Von Neumann" bottleneck
-
Theory:
- one or more data types
- operations on these types
- laws that describe the relationship between values and operations
- Normally, a theory does not describe mutations (change something but keep the identity)
-
Theories without Mutation
- Pylonomial
- String
-
consequence in programming
- avoid mutations
- have a power way to abstract operations and functions.
-
The substitution model
- lambda calculus
- only to expression don't have a side effect
- termination
def loop: Int = loop
- unreduced arguments
-
Call-by-name and call-by-value
def test(x: Int, y: Int) = x * x test(2, 3) test(3 + 4, 8) test(7, 2 * 4) test(3 + 4, 2 * 4)
-
CBV, CBN, and termination
- CBV termination --> CBN termination
- Not vice versa
- example
def first(x: Int, y: Int) = x first(7, loop)
- enforce call by name
=>
-
Conditional expressions
- if-else not a statement, just a expression.
- Value and definitions
scala> def loop: Boolean = loop && loop loop: Boolean scala> def x = loop x: Boolean scala> val x = loop java.lang.StackOverflowError at .loop(<console>:12)
-
Square root with Newton's Method
def abs(x: Double) = if (x < 0) -x else x def sqrtIter(guess: Double, x: Double): Double = if (isGoodEnough(guess, x)) guess else sqrtIter(improve(guess,x), x) def isGoodEnough(guess: Double, x: Double) = abs(guess * guess - x) < 0.001 def improve(guess: Double, x: Double) = (guess + x / guess) / 2 def sqrt(x: Double) = sqrtIter(1.0, x)
-
Tail recursion: Implementation consideration. If a function calls itself as its last action, the function's stack frame can be reused. This is called tail recursion. Tail recursive function are iterative processes. (anotation: @tailrec)
-
gcd
is tail recursiondef gcd(a: Int, b: Int): Int = { if (b == 0) a else gcd(b, a % b) }
-
factorial
is notdef factorial(n: Int) = if (n == 0) 1 else n * factorial(n - 1)
-
but we can rewrite
factorial
in tail recursion form.def factorial(n: Int): Int = { def loop(acc: Int, n: Int): Int = if (n == 0) acc else loop(acc * n, n - 1) loop(1, n) }