Functional programming has evolved significantly since its origins in lambda calculus. Key developments include Lisp (1958), ML (1973), Haskell (1990), and more recently languages for the JVM like Scala (2004) and Clojure (2007). Functional concepts like immutable data, higher-order functions, lazy evaluation and currying allow a more declarative style and improved performance. Advances like tail call optimization and parallelism address early performance issues. Future areas include dependent types as in Idris and embracing functional principles in mainstream languages like Java 8. Functional programming changes how we think about solving problems.
2. Functional Programming - today’s special
…
• Timeline – parallel to the imperative timeline
• Languages
• Concepts
Goal: Bootstrapping for functional programming
4. Theory of Computation <- Math + Logic
Alonzo Church
Lambda Calculus
Alan Turing
Turing Machine
Stephen Kleene
Recursive Function
Theory
5. Lambda Calculus
It’s a formal system in mathematical logic for
expressing computation based on function
abstraction and application using variable binding
and substitution.
~ Wikipedia
6. Lambda Calculus – Fundamental Idea
x //variable
t //lambda term
Λx.t //lambda abstraction
Λx. x2
+1 // x is bound in t by Λx
Λx. x2
+1(2) = 22
+1 = 5 //application
Note: A lambda abstraction has no name
7. LISP - 1958
LIST Processor
Influenced by Church’s
lambda calculus
notation
Multi-paradigm, pre-fix
notation
John McCarthy
9. LISP – Well known dialects
• Scheme – 1970
• Common Lisp – 1984
• Racket – 1984
• Clojure – 2007
• Lisp Flavoured Erlang (LFE) – 2008 (v1 March
2016)
10.
11. Academic Research (1960 – 1985)
• ISWIM – If You See What I Mean – 1966
• SASL – St. Andrews Static Language – 1972
• ML – MetaLanguage – 1973 => Ocaml, F#
• Miranda – 1985 => Haskell
12. Back to some Lambda Calculus
F(x) = x3
+4x //F(x) id a first-order function
//maps values to values
dF(x)/dx = 3x2
+ 4
//d/dx maps functions to functions
d/dx is an example of higher-order functions
13. Higher-order Functions
A function is a higher-order function if:
• It takes at least one function as an argument OR
• It returns a function
All other functions are first–order functions!
14. Erlang - 1984
Designed for massive scalable soft real time
systems
Fault-tolerance and concurrency
15. Erlang
Multi-paradigm, but has a functional core
•First-class functions
Functions can be passed to functions
First-class citizens
=> Higher-order functions
•Immutable values
Immutable “variables” – creating new values instead
Minimizing moving parts has benefits
17. Erlang – Higher-order functions
%find total salaries exceeding 30000
MoreThan30K = fun(Y) -> Y > 30000 end.
lists:filter(MoreThan30K,T).
>> [37500, 49500]
You just learnt “map” and “filter”. Let them sink in!
18. Haskell - 1990
• Full blown functional language
• Algebraic data types and type classes
• No statements – the entire program is an
”expression”
• Pattern matching
• Lazy evaluation
• Purely functional – functions have no side effect
19. Haskell – Algebraic Data Types (ADT)
• Derived from Type Theory
• A composite type - formed by combining other
types
data List a = Nil
| Cons a (List a)
data Tree a = Node a (Tree a) (Tree a)
| Nil
20. Haskell – Pattern Matching
-- construct a List from an list
makeList (x:xs) = Cons x (makeList xs)
makeList [] = Nil
-- construct an list from a List
makeArr (Cons x (xs)) = x:(makeArr xs)
makeArr Nil = []
23. Currying
Introduced by Shönfinkel
Lambda calculus deals with single argument
functions
What about multiple argument functions then?
If F(X, Y, Z) -> N, then
curry(F): X -> (Y -> (Z -> N))
24. Lambda Calculus - Currying
F(X, Y, Z) = X + Y + Z
F(1, 2, 3) = Fcurried(1)(2)(3)
//apply only one argument at a time
Fcurried (1) = F’curried
F’curried(2) = F”curried
F”curried(3) = 6
25. OCaml - 1996
• Multi-paradigm
• Derived from ML
• Static type system helps eliminate runtime
problems
• Emphasis on performance – good optimizing
compiler
26. Currying in OCaml
# let plus x y z = x + y + z;;
# plus 1 2 3;;
- : int = 6
# let x = plus 1;;
val x : int -> int -> int = <fun>
27. Currying in OCaml
# let y = x 2;;
val y : int -> int = <fun>
# y 3;;
- : int = 6
Cool, but what’s the use of all this?
28. Currying in OCaml
Function to add 2 to all numbers of a list
let add2 x = x + 2
List.map add2 [1;2;3;4;5];;
Function to add 3 to all numbers of a list
let add3 x = x + 3
List.map add3 [1;2;3;4;5];;
29. Currying in OCaml
With currying:
let add x y = x + y
List.map (add 2) [1;2;3;4;5]
List.map (add 3) [1;2;3;4;5]
•Better reuse of code
•Improved readability
32. Scala
• Seamless integration with
Java
• Combines object oriented
programming and functional
programming
• Type inference
• Higher order functions
• Pattern matchingMartin Odersky
33. Scala
Simple functional code to find the length of a list:
(no loops in functional programming!)
def listLength (list: List[_]): Int =
list match {
case Nil => 0
case _ => 1 + listLength(list.tail)
}
Any problems here?
35. Scala - TCO
No! You have tail recursion and tail-recursion
optimization (TCO)
def length(as: List[_]): Int = {
@tailrec
def length0(as: List[_], count: Int = 0): Int =
as match {
case Nil => count
case head :: tail => length0(tail, count+ 1)
}
length0(as)
}
36. Scala - TCO
Simplistic essence of tail-call optimization
Execution state
Single, reusable
stack frame
37. Clojure - 2007
Our fascination with LISP is never ending!
Rich Hickey
• LISP for the JVM
• Java-Clojure
interoperability
• Other implementations –
ClojureScript,
ClojureCLR
• Used in creative
computing!
39. Clojure
Pure functions
•Referential Transparency
•No side effects – stateless programs
•Given an argument, the function must return the
same value! (fib 4) is always 3, for example.
=> Values (fib K) can be reused for all K
Speed up? Caching?
40. Clojure - Memoization
(def m-fib
(memoize (fn [n]
(condp = n
0 1
1 1
(+ (m-fib (- n 1)) (m-fib (- n 2)))))))
42. Java 8 - 2014
The exciting times begin!
•Lambdas
•Stream Interface – lazy evaluation!
•Functional Interfaces
•Default methods – for backward compatibility
A mammoth like Java embracing the functional
paradigm is a big cue about the times to come.
44. Lazy Evaluation
• Evaluate an expression only when it’s use is
encountered
• Values are created only when needed
• Reduction in memory footprint
• Fast
• In combination with memoization, results in very
efficient functional code
45. Problem
Find the number of first deliveries of overs, when a
batsman who scored at least five centuries and hit at
least 100 sixes, was out.
47. Java 8 - Parallelism
Parallel execution. Almost zero change to your code.
allDeliveries.parallelStream()
.filter(d -> d.deliveryNumber() == 1)
.filter(d -> d.wicket())
.map(d -> d.getBatsman())
.filter(b -> b.totalCenturies() >= 5)
.filter(b -> b.totalSixes >= 100)
.count() //terminal operation
48. Java 8
• No intentions of becoming a full blown functional
language
• Lambdas and lazy evaluation provide a big boost
• Readability improved – anonymous classes not
needed
• Reusability improved – lambdas, functional
interfaces
• Java 9 – better Stream interface expected
49. Idris – A peek into the future
• Data types are first class objects!
• You can generate data types, store them, pass
them around
• Dependent types were developed by Haskell
Curry to deepen the connection between
programming and logic (Curry-Howard
correspondence)
• Dependent types – types that depend on values!
• Influenced by Agda
50. Idris – dependent types
ListType : (singleton : Bool) -> Type
ListType False = List Nat
ListType True = Nat
sumList : (singleton : Bool)->ListType singleton->Nat
sumList False (x :: xs) = x + sumList False xs
sumList False [] = 0
sumList True x = x
51. Why Functional Programming
• Higher levels of behavioural abstraction – tell what
is to be done, not how to do it
• Agile Methodologies - Code reuse, readability
• Correctness
• Exploiting massively parallel hardware
54. Recap
• Tail-call recursion and TCO
• Pure functions, referential transparency
• Memoization
• Lazy evaluation
• Parallelism
• Dependent data types
55. A programming language that does not change the way you
think is not worth knowing ~ Alan Perlis
Functional programming changes the way you think.
It’s worth knowing!