Functional Programming
ExperTalks 2015-09-11
Leena Bora, Equal Experts
Christian Hujer, Nelkinda Software Craft
Flying to other stars
Methods that don’t work
What are the problems?
No (known) medium in space.
No chemicals in space (i.e. no oxygen).
Many more.
One of the biggest:
Speed of Light = speed limit
Can we “break” the speed limit?
Sci-Fi authors: “Yes” Scientists: “No!”
Miguel Alcubierre from Mexico …
… watched Star Trek TNG …
… and then had the idea for this:
ds2 = -(α2 - βi βi) dt2 + 2βi dxi dt + γij dxidxj
which I don’t really understand,
but if it works...
… it would allow this
Further Information
Alcubierre Drive (Wikipedia)
Miguel Alcubierre (Wikipedia)
“The warp drive: hyper-fast travel within
general relativity” - Miguel Alcubierre, 1994
Warp Drive (Wikipedia)
RF resonant cavity thruster (Wikipedia)
History of
Functional Programming
1903 - 1995
1930s
𝜆 calculus
1936
untyped 𝜆 calculus
1940
simple typed 𝜆 calculus
Alonzo Church: Lambda-Calculus
John McCarthy: Lisp
1927 - 2011
1958
Lisp
1959
Garbage Collection
1961
Utility Computing
(Cloud!)
1971
Turing Award
John Backus
1924 - 2007
1957
FORTRAN
1960
Backus-Naur-Form
1977
Turing Award, FP
“Can Programming be
Liberated from the von
Neumann Style?”
Milestones
1936 Lambda Calculus (Church & Rosser)
1958 Lisp (McCarthy)
1963 Algol 60 (Naur et al)
1966 ISWIM (Landin)
1969 NPL, ML, HOPE
1973 SASL
1986 Miranda
1992 Haskell
2007 Clojure
2013 Java 8
Moore’s Law (1965)
Gordon E. Moore
●*1929
●Co-founder of Intel
~ “Number of
transistors doubles
every 18 months”
⇒ More GHz
But for how long?
Amdahl’s Law (1967)
Gene Amdahl
●*1922
●IBM Mainframes
●Amdahl
Corporation
Amdahl’s Law
Given
●𝑛 ∊ ℕ, the number of threads of execution
●B ∊ [0, 1], strictly serial fraction of algorithm
Time T(𝑛) it takes to finish with n threads is
T(𝑛) = T(1)(B + 1/𝑛 (1 − B))
Therefore, the theoretical speedup S(𝑛) is
S(𝑛) = T(1) / T(𝑛) = 1 / (B + 1/𝑛 (1 - B))
Gustafson’s Law
John Gustafson
●*1955
●HPC
●Computer Clusters
Gustafson’s Law
Given a the sequential time, b the parallel time,
P the number of processors,
a + b single thread time
a + P b sequential time
(a + P b) / (a + b) speedup
α = a / (a + b)
sequential fraction S(P):
S(P) = α + P (1 − α) = P − α (P − 1)
To run fast
Parallelism
Avoid Race conditions
Alonzo Church (Wikipedia)
John McCarthy (Wikipedia)
John Backus (Wikipedia)
Functional Programming History (Wikipedia)
Some History of Functional Programming Languages (D.
A. Turner)
Gordon Moore (Wikipedia)
Moore’s Law (Wikipedia)
Gene Amdahl (Wikipedia)
Amdahl’s Law (Wikipedia)
John Gustafson (Wikipedia)
Gustafson’s Law (Wikipedia)
History of Functional Programming
References
Programming Paradigm
It is all about “functions”
What is Functional Programming?
f(x) = 2x + 3
f(2) = 4 + 3 = 7
The value of x will never change inside a mathematical
function.
Same input, same output - all the time!
Call f() multiple times, without any side-effects.
We don’t have to recalculate f(2), replace occurrence of
f(2) with 7 (Referential Transparency)
f(x) = 2x² − 2x + 3
Pure Function
public int calculate(int x) {
return (2 * x) + 3;
}
calculate(2) = 7
calculate(2) = 7
public class Account {
int balance;
public Account(int balance) {
this.balance = balance;
}
public int credit(int amount) {
balance = balance + amount;
return balance;
}
}
Account account = new Account(100);
account.credit(500); // → balance == 600
account.credit(500); // → balance == 1100
class Account {
final int balance;
public Account(int balance) {
this.balance = balance;
}
public Account credit(int amount) {
return new Account(balance + amount);
}
}
Account account = new Account(100)
Account currentAccountState = account.credit(500)
===> currentAccountState(600)
Account newAccountState = currentAccountState.credit(500)
===> newAccountState(1100)
account.credit(500)
===> currentAccount(600)
Modifying global variable / data structure
Modifying input value
Throwing an exception
Read / Write (File, Console, Database)
Communication with External System
Side Effects
Thin layer of impure functions
(DB, I/O, exceptions)
Pure functions at the core
Why Pure Functions?
No Side-effects
A function f is said to be a “pure function” if
f(x) is “referentially transparent”
Memoization
Execution Order can be rearranged (!)
Local Reasoning
Parallel Execution
public int square (int number) {
return number * number;
}
Functional Programming is so called
because a program consists of
“pure functions” & “functions”
Where FP and OOP meet for the DIP
Higher-Order Functions
No function as argument,
and no function as return
First-Order vs Higher-Order
Function as argument,
or function as return
(or both)
Workarounds if unavailable
Function Pointer Types
Function Pointers
One-Element Interfaces
Objects
1 #include <stdlib.h> // qsort
2 #include <string.h> // strcmp
3
4 static int strptrcmp(const void *l1, const void *l2) {
5 return strcmp(*(const char **)l1, *(const char **)l2);
6 }
7
8 static char **lines;
9 static size_t numberOfLines;
10
11 qsort(lines, numberOfLines, sizeof(char *), strptrcmp);
Higher-Order Functions in C
Example: qsort()
1 enum AccountComparator implements Comparator<Account> {
2 INSTANCE;
3 public int compare(Account a1, Account a2) {
4 return Integer.compare(a1.balance, a2.balance);
5 }
6 }
7
8 List<Account> accounts = …;
9 accounts.sort(AccountComparator.INSTANCE);
Higher-Order Functions in Java
Example: List.sort()
Method References
Lambda Expressions
Syntactic sugar for higher-order functions.
Underneath: generated anonymous classes.
Improvements in Java 8
1 class Account {
2 int balance;
3 Account(int balance) { this.balance = balance; }
4 public static final Comparator<Account> BY_BALANCE =
5 new Comparator<Account>() {
6 public int compare(Account a1, Account a2) {
7 return compare(a1.balance, a2.balance);
8 }
9 };
10 }
11
12 List<Account> accounts;
13 accounts.sort(BY_BALANCE);
Java 5 Anonymous Class
1 class Account {
2 int balance;
3 Account(int balance) { this.balance = balance; }
4 public static final Comparator<Account> BY_BALANCE =
5
6 ( a1, a2) -> {
7 return compare(a1.balance, a2.balance);
8 }
9 ;
10 }
11
12 List<Account> accounts;
13 accounts.sort(BY_BALANCE);
Java 8 Block Lambda
1 class Account {
2 int balance;
3 Account(int balance) { this.balance = balance; }
4 public static final Comparator<Account> BY_BALANCE =
5
6 ( a1, a2) ->
7 compare(a1.balance, a2.balance)
8
9 ;
10 }
11
12 List<Account> accounts;
13 accounts.sort(BY_BALANCE);
Java 8 Expression Lambda
1 class Account {
2 int balance;
3 Account(int balance) { this.balance = balance; }
4 public static final Comparator<Account> BY_BALANCE =
5 (a1, a2) -> compare(a1.balance, a2.balance);
6 }
7
8 List<Account> accounts;
9 accounts.sort(BY_BALANCE);
Java 8 Expression Lambda
1 final JFrame frame = new JFrame("Hello");
2 final JButton button = new JButton("Click me!");
3 button.addActionListener(new ActionListener() {
4 @Override
5 public void actionPerformed(final ActionEvent e) {
6 showMessageDialog(frame, "Hello, world!");
7 }
8 });
9 frame.add(b);
10 frame.pack();
11 frame.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
12 frame.setVisible(true);
Single Method Callback
Java 5 Anonymous Class
1 final JFrame frame = new JFrame("Hello");
2 final JButton button = new JButton("Click me!");
3 button.addActionListener(e ->
4
5
6 showMessageDialog(frame, "Hello, world!")
7
8 );
9 frame.add(b);
10 frame.pack();
11 frame.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
12 frame.setVisible(true);
Single Method Callback
Java 8 Expression Lambda
Java 8 Instance Method References
1 public class Application {
2 Application() {
3 final JMenuItem open = new JMenuItem("Open...");
4 final JMenuItem save = new JMenuItem("Save");
5 open.addActionListener(this::open);
6 save.addActionListener(this::save);
7 }
8 private void open(final ActionEvent e) {
9 // ...
10 }
11 private void save(final ActionEvent e) {
12 // ...
13 }
14 }
Java 8 Stream.forEach()
1 import java.io.*;
2 import static java.lang.System.*;
3
4 public class Sort {
5 private static BufferedReader getIn() {
6 return new BufferedReader(new InputStreamReader(in));
7 }
8 public static void main(final String... args) throws
IOException {
9 try (final BufferedReader in = getIn()) {
10 in.lines().sorted().forEach(out::println);
11 }
12 }
13 }
What if you want to reuse A without B?
Dependency Inversion Principle
Component A Component B
What if you want to reuse A without B?
Dependency Inversion Principle
Component A Component B
Sort Article
What if you want to reuse A without B?
Dependency Inversion Principle
Component A Component B
Sort ArticleComparable
Higher Order Functions
Are a form of polymorphism
Serve the Dependency Inversion Principle
Decouple software entities
Make software entities reusable
Higher-Order Functions and OO
Higher-Order Functions can always be
expressed using Objects.
Not every expression using Objects is also a
Higher-Order Function.
I recommend to avoid calling methods that
have Methods with side-effects as
parameters or return values “Higher-Order
Functions”.
Higher-Order Functions
References
Higher-order function (Wikipedia)
How is dependency inversion related to
higher-order functions? (StackExchange)
Imperative vs Declarative
Find Even Numbers
Double it
Sum it up
public int calculate() {
int[] numbers = {1, 5, 10, 9, 12};
List<Integer> doubledEvenNumbers = new ArrayList<>();
for (int number : numbers)
if (number % 2 == 0)
doubleEvenNumbers.add(num * 2);
int total = 0;
for (int even : doubleEvenNumbers)
total = total + even;
return total;
}
Imperative Style
Declarative Style
val list = List(1, 5, 10, 9, 12)
val total = list.filter( number => number % 2 == 0)
.map ( evenNumber => evenNumber * 2)
.sum
Imperative Paradigm
How to do it
Mutability
Use locking / synchronization for thread safety
Side effects
null values
Declarative Paradigm
What to do
Immutability
No loops (recursion)
Persistent Data
Structures
Get popcorn, lean back, relax and enjoy
If you know
Git internals
Now listen carefully and learn something
about Git at the same time!
If you do not know
Git internals
“All fields final” - even in data structures.
Previous version is preserved.
Modifying data structures actually creates
copies of modified parts, references of
unmodified parts.
Persistent Data Structure
Three Levels of Persistence
1.Partially Persistent
Query all versions
Update only latest version
2.Fully Persistent
Query all versions
Update all versions
3.Confluently Persistent
Combinators -> Directed Acyclic Graph
Immutable (Persistent) Object
1 class Point {
2 final int x;
3 final int y;
4 Point(final int x, final int y) {
5 this.x = x;
6 this.y = y;
7 }
8 }
Persistent Data Structures: List
1 public class ListNode<T> {
2 public final ListNode<T> next;
3 public final T data;
4 public ListNode(final T data) { this(null, data); }
5 public ListNode(final ListNode<T> next, final T data) {
6 this.next = next;
7 this.data = data;
8 }
9 }
Persistent Data Structures: List
fedcba
Persistent Data Structures: List
fedcba
c’b’a’
Persistent Data Structures: Tree
1 public class TreeNode<T> {
2 public final TreeNode<T> left;
3 public final TreeNode<T> right;
4 public final T data;
5 public TreeNode(final T data) {this(null, null, data);}
6 TreeNode(TreeNode<T> left, TreeNode<T> right, T data) {
7 this.left = left;
8 this.right = right;
9 this.data = data;
10 }
11 }
Persistent data structure (Wikipedia)
Data Structures (Clojure)
Persistent Data Structures
References
Lazy Evaluation
Evaluation Strategies
Strict Evaluation
Non-strict Evaluation
int x = 5 * 3;
System.out.println(x);
int x = product(2);
System.out.println(x);
public int product(int num) {
System.out.println("product method");
return num * 3;
}
product method
6
Evaluate immediately at the time of
assignment
Call By Value
Call By Reference
Strict Evaluation
multiply(true, 10 / 0);
int multiply(boolean flag, int i) {
if (flag)
return 100;
else
return i * 5;
}
// → Division by zero
Non Strict Evaluation
Function parameter assignment
Variable assignment
2 types of assignments
val result = product(true, 10/0)
println(result)
def product(flag: => Boolean, num: => Int) = {
if (flag)
100
else
5 * num
}
// → 100
Call By Name (Function Parameters)
Call By Need (Variables)
Call By Need = Lazy Evaluation
Non Strict Evaluation
public class Singleton {
private static Singleton instance = null;
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) {
System.out.println("Create new for the first time.");
instance = new Singleton();
}
return instance;
}
public static void main(final String... args) {
Singleton.getInstance();
Singleton.getInstance();
}
}
lazy val result = func("Hello")
println("333")
println(result)
println(result)
def func(str: String) = {
println("Inside func")
str + ", World!"
}
333
Inside func
Hello, World!
Hello, World!
Avoids unnecessary computation
→ More Performance
Evaluates only once
→ More Performance
Infinite Data Structures (Streams)
Why Lazy Evaluation?
Lazy Description
of Odd Numbers
lazy 1 lazy 3 lazy 5 lazy 7 lazy 9 So on …
1 3 5 7 9 So on …
Avoids unnecessary computation
→ More Performance
Infinite Data Structures (Streams)
Modularity
Why Lazy Evaluation?
Haskell
By default Non Strict Evaluation
Partial Functions
𝑓 : ℕ0 × ℕ0 → ℕ0
𝑓(𝑥, 𝑦) = 𝑥 + 𝑦
Defined ∀ 𝑥: 𝑥 ∊ ℕ0
⇒ Total Function
Partial Functions in Mathematics
typedef uint32_t u32;
u32 f(u32 x, u32 y)
{
return x + y;
}
𝑓 : ℕ0 × ℕ0 → ℕ0
𝑓(𝑥, 𝑦) = 𝑥 + 𝑦
Defined ∀ 𝑥: 𝑥 ∊ ℕ0
⇒ Total Function
𝑓 : ℕ0 × ℕ0 → ℕ0
𝑓(𝑥, 𝑦) = 𝑥 − 𝑦
Only when 𝑥 ≥ 𝑦
⇒ Partial Function
Partial Functions in Mathematics
typedef uint32_t u32;
u32 f(u32 x, u32 y)
{
return x + y;
}
u32 f(u32 x, u32 y)
{
return x - y;
}
Partial Functions in Scala
val isEven: PartialFunction[Int, String] = {
case x if x % 2 == 0 => x + "is even"
}
val isOdd: PartialFunction[Int, String] = {
case x if x % 2 == 1 => x + "is odd"
}
val sample = 1 to 10
val evenNumbers = sample collect isEven
val numbers = sample map (isEven orElse isOdd)
Partial Functions
“You almost never have an excuse for writing
a partial function!” - Haskell Wiki
Partial Functions
References
Partial Function (Wikipedia)
Partial Functions (Haskell Wiki)
PartialFunction (Scala API)
Function Composition
float x, y, z;
y = g(x);
z = f(y);
z = f(g(x));
“Function Composition” is applying one function to the
results of another.
Haskell
foo = f . g
Scala
val add = (x: Int) => x + 10
val subtract = (x: Int) => x - 5
List(10, 20, 30).map(add and Then subtract)
First Class Composition
Currying
“Currying is similar to the process of calculating
a function of multiple variables for some given
values on paper.” - Wikipedia
Currying
Currying for the poor:
Method Overloading
class Complex {
final double real;
final double imaginary;
Complex(double real, double imaginary) {
this.real = real;
this.imaginary = imaginary;
}
static Complex real(double real) {
return new Complex(real, 0);
}
}
Formal Definition of Currying
Given a function f of type f : (X × Y) → Z,
currying it makes a function
curry(f): X → (Y → Z)
That is, curry(f) takes an argument of type X
and returns a function of type Y → Z.
Currying in Scala
def add(x: Int, y: Int) = x + y
add(1, 2) // 3
add(7, 3) // 10
def add(x: Int)(y: Int) = x + y
add(1)(2) // 3
add(7)(3) // 10
Currying existing Functions
def add(x: Int, y: Int) = x + y
val addCurried = Function.curried(add _)
add(1, 2) // 3
addCurried(1)(2) // 3
Currying (Wikipedia)
Function Currying in Scala (Code Commit)
Currying
References
Questions?
Thank you!
Images used may be subject to copyright. Use
in this presentation on the basis of fair use
for the purpose of teaching and education.
References
Backup Slides follow
Not part of the presentation
Reducing the Transformation Priority
Premise for Functional Programming
Functional Programming
and TPP
Original
{} → nil
nil → constant
constant → constant+
constant → scalar
statement → statements
unconditional → if
scalar → array
array → container
statement → recursion
if → while
expression → function
variable → assignment
Transformation Priority Premise
Functional
{} → nil
nil → constant
constant → constant+
n/a
statement → statements
unconditional → if
scalar → list
n/a
statement → recursion
n/a (use recursion)
expression → function
n/a
More Examples
main(Argv) :- echo(Argv).
echo([]) :- nl.
echo([Last]) :- write(Last), echo([]).
echo([H|T]) :- write(H), write(' '), echo(T).
Echo in Prolog
qsort :: (Ord a) => [a] -> [a]
qsort [] = []
qsort (x:xs) =
let left = qsort [a | a <- xs, a <= x]
right = qsort [a | a <- xs, a > x]
in left ++ [x] ++ right
--or even shorter
qsort (x:xs) =
qsort [a | a <- xs, a <= x]
++ [x] ++
qsort [a | a <- xs, a > x]
Quicksort in Haskell
Quicksort in Perl 5
sub qsort {
return @_ if @_ < 2;
my $p = splice @_, int rand @_, 1;
qsort(grep$_<$p,@_), $p,
qsort(grep$_>=$p,@_);
}
Quicksort in Scala
def qsort[T](list: List[T])(implicit ev1: T =>
Ordered[T]): List[T] = list match {
case Nil => Nil
case p :: xs =>
val (lesser, greater) = xs partition (_ <=
p)
qsort(lesser) ++ List(p) ++ qsort(greater)
}
Alternate and Extended
Slides
f(x) = 2x2 - 2x + 3
f(x) = 2x2 - 2x + 3
f(4) = 2*4*4 - 2*4 + 3 = 32 - 14 + 3 = 27
The value of x will never change inside a mathematical
function.
Same input, same output - all the time!
Call f() multiple times, without any side-effects.
We don’t have to recalculate f(4), replace occurrence of
f(4) with 27 (Referential Transparency)
public class Account {
int balance;
public Account(int balance) {
this.balance = balance;
}
public int credit(int amount) {
return balance += amount;
}
}
Account account = new Account(100);
account.credit(500); // → balance == 600
account.credit(500); // → balance == 1100
public class Account {
final int balance;
public Account(int balance) {
this.balance = balance;
}
public Account credit(int amount) {
return new Account(balance + amount);
}
}
Account account = new Account(100);
Account currentAccountState = account.credit(500);
Account newAccountState = currentAccountState.credit(500);
account.credit(500); // → currentAccount(600)
public int calculate() {
int[] numbers = {1, 5, 10, 9, 12};
List<Integer> doubledEvenNumbers = new ArrayList<>();
int total = c;
for (int number : numbers)
if (number % 2 == 0)
total += num * 2;
return total;
}
Imperative Style
Declarative Style
public int calculate() {
return IntStream.of(1, 5, 10, 9, 12)
.filter(number -> number % 2 == 0)
.map(number -> number * 2)
.sum();
}
Declarative Style
def calculate() {
List(1, 5, 10, 9, 12)
.filter(number => number % 2 == 0)
.map(number => number * 2)
.sum
}
public int product(int num) {
System.out.println("product method");
return num * 3;
}
int x = 5 * 3;
System.out.println(x);
x = product(2);
System.out.println(x);
15
product method
6
int multiply(boolean flag, int i) {
if (flag)
return 100;
else
return i * 5;
}
System.out.println(multiply(true, 10 / 0));
// → Division by zero
public class Singleton {
private Singleton() {
System.out.println("Create new for the first time.");
}
public static Singleton getInstance() {
return LazyHolder.INSTANCE;
}
private static class LazyHolder {
private static final Singleton INSTANCE = new
Singleton();
}
}
public class Singleton {
public static final Singleton
INSTANCE = new Singleton();
private Singleton() {
System.out.println("Init");
}
}
public enum Singleton {
INSTANCE;
private Singleton() {
System.out.println("Init");
}
}

Functional programming

  • 1.
    Functional Programming ExperTalks 2015-09-11 LeenaBora, Equal Experts Christian Hujer, Nelkinda Software Craft
  • 2.
  • 3.
  • 4.
    What are theproblems? No (known) medium in space. No chemicals in space (i.e. no oxygen). Many more. One of the biggest: Speed of Light = speed limit
  • 5.
    Can we “break”the speed limit? Sci-Fi authors: “Yes” Scientists: “No!”
  • 6.
  • 7.
    … watched StarTrek TNG …
  • 8.
    … and thenhad the idea for this: ds2 = -(α2 - βi βi) dt2 + 2βi dxi dt + γij dxidxj which I don’t really understand, but if it works...
  • 9.
    … it wouldallow this
  • 10.
    Further Information Alcubierre Drive(Wikipedia) Miguel Alcubierre (Wikipedia) “The warp drive: hyper-fast travel within general relativity” - Miguel Alcubierre, 1994 Warp Drive (Wikipedia) RF resonant cavity thruster (Wikipedia)
  • 11.
  • 12.
    1903 - 1995 1930s 𝜆calculus 1936 untyped 𝜆 calculus 1940 simple typed 𝜆 calculus Alonzo Church: Lambda-Calculus
  • 13.
    John McCarthy: Lisp 1927- 2011 1958 Lisp 1959 Garbage Collection 1961 Utility Computing (Cloud!) 1971 Turing Award
  • 14.
    John Backus 1924 -2007 1957 FORTRAN 1960 Backus-Naur-Form 1977 Turing Award, FP “Can Programming be Liberated from the von Neumann Style?”
  • 16.
    Milestones 1936 Lambda Calculus(Church & Rosser) 1958 Lisp (McCarthy) 1963 Algol 60 (Naur et al) 1966 ISWIM (Landin) 1969 NPL, ML, HOPE 1973 SASL 1986 Miranda 1992 Haskell 2007 Clojure 2013 Java 8
  • 17.
    Moore’s Law (1965) GordonE. Moore ●*1929 ●Co-founder of Intel ~ “Number of transistors doubles every 18 months” ⇒ More GHz But for how long?
  • 21.
    Amdahl’s Law (1967) GeneAmdahl ●*1922 ●IBM Mainframes ●Amdahl Corporation
  • 22.
    Amdahl’s Law Given ●𝑛 ∊ℕ, the number of threads of execution ●B ∊ [0, 1], strictly serial fraction of algorithm Time T(𝑛) it takes to finish with n threads is T(𝑛) = T(1)(B + 1/𝑛 (1 − B)) Therefore, the theoretical speedup S(𝑛) is S(𝑛) = T(1) / T(𝑛) = 1 / (B + 1/𝑛 (1 - B))
  • 24.
  • 25.
    Gustafson’s Law Given athe sequential time, b the parallel time, P the number of processors, a + b single thread time a + P b sequential time (a + P b) / (a + b) speedup α = a / (a + b) sequential fraction S(P): S(P) = α + P (1 − α) = P − α (P − 1)
  • 27.
  • 28.
    Alonzo Church (Wikipedia) JohnMcCarthy (Wikipedia) John Backus (Wikipedia) Functional Programming History (Wikipedia) Some History of Functional Programming Languages (D. A. Turner) Gordon Moore (Wikipedia) Moore’s Law (Wikipedia) Gene Amdahl (Wikipedia) Amdahl’s Law (Wikipedia) John Gustafson (Wikipedia) Gustafson’s Law (Wikipedia) History of Functional Programming References
  • 29.
    Programming Paradigm It isall about “functions” What is Functional Programming?
  • 30.
    f(x) = 2x+ 3 f(2) = 4 + 3 = 7 The value of x will never change inside a mathematical function. Same input, same output - all the time! Call f() multiple times, without any side-effects. We don’t have to recalculate f(2), replace occurrence of f(2) with 7 (Referential Transparency)
  • 31.
    f(x) = 2x²− 2x + 3
  • 32.
    Pure Function public intcalculate(int x) { return (2 * x) + 3; } calculate(2) = 7 calculate(2) = 7
  • 33.
    public class Account{ int balance; public Account(int balance) { this.balance = balance; } public int credit(int amount) { balance = balance + amount; return balance; } } Account account = new Account(100); account.credit(500); // → balance == 600 account.credit(500); // → balance == 1100
  • 34.
    class Account { finalint balance; public Account(int balance) { this.balance = balance; } public Account credit(int amount) { return new Account(balance + amount); } } Account account = new Account(100) Account currentAccountState = account.credit(500) ===> currentAccountState(600) Account newAccountState = currentAccountState.credit(500) ===> newAccountState(1100) account.credit(500) ===> currentAccount(600)
  • 35.
    Modifying global variable/ data structure Modifying input value Throwing an exception Read / Write (File, Console, Database) Communication with External System Side Effects
  • 37.
    Thin layer ofimpure functions (DB, I/O, exceptions) Pure functions at the core
  • 38.
    Why Pure Functions? NoSide-effects A function f is said to be a “pure function” if f(x) is “referentially transparent” Memoization Execution Order can be rearranged (!) Local Reasoning Parallel Execution public int square (int number) { return number * number; }
  • 39.
    Functional Programming isso called because a program consists of “pure functions” & “functions”
  • 40.
    Where FP andOOP meet for the DIP Higher-Order Functions
  • 41.
    No function asargument, and no function as return First-Order vs Higher-Order Function as argument, or function as return (or both)
  • 42.
    Workarounds if unavailable FunctionPointer Types Function Pointers One-Element Interfaces Objects
  • 43.
    1 #include <stdlib.h>// qsort 2 #include <string.h> // strcmp 3 4 static int strptrcmp(const void *l1, const void *l2) { 5 return strcmp(*(const char **)l1, *(const char **)l2); 6 } 7 8 static char **lines; 9 static size_t numberOfLines; 10 11 qsort(lines, numberOfLines, sizeof(char *), strptrcmp); Higher-Order Functions in C Example: qsort()
  • 44.
    1 enum AccountComparatorimplements Comparator<Account> { 2 INSTANCE; 3 public int compare(Account a1, Account a2) { 4 return Integer.compare(a1.balance, a2.balance); 5 } 6 } 7 8 List<Account> accounts = …; 9 accounts.sort(AccountComparator.INSTANCE); Higher-Order Functions in Java Example: List.sort()
  • 45.
    Method References Lambda Expressions Syntacticsugar for higher-order functions. Underneath: generated anonymous classes. Improvements in Java 8
  • 46.
    1 class Account{ 2 int balance; 3 Account(int balance) { this.balance = balance; } 4 public static final Comparator<Account> BY_BALANCE = 5 new Comparator<Account>() { 6 public int compare(Account a1, Account a2) { 7 return compare(a1.balance, a2.balance); 8 } 9 }; 10 } 11 12 List<Account> accounts; 13 accounts.sort(BY_BALANCE); Java 5 Anonymous Class
  • 47.
    1 class Account{ 2 int balance; 3 Account(int balance) { this.balance = balance; } 4 public static final Comparator<Account> BY_BALANCE = 5 6 ( a1, a2) -> { 7 return compare(a1.balance, a2.balance); 8 } 9 ; 10 } 11 12 List<Account> accounts; 13 accounts.sort(BY_BALANCE); Java 8 Block Lambda
  • 48.
    1 class Account{ 2 int balance; 3 Account(int balance) { this.balance = balance; } 4 public static final Comparator<Account> BY_BALANCE = 5 6 ( a1, a2) -> 7 compare(a1.balance, a2.balance) 8 9 ; 10 } 11 12 List<Account> accounts; 13 accounts.sort(BY_BALANCE); Java 8 Expression Lambda
  • 49.
    1 class Account{ 2 int balance; 3 Account(int balance) { this.balance = balance; } 4 public static final Comparator<Account> BY_BALANCE = 5 (a1, a2) -> compare(a1.balance, a2.balance); 6 } 7 8 List<Account> accounts; 9 accounts.sort(BY_BALANCE); Java 8 Expression Lambda
  • 50.
    1 final JFrameframe = new JFrame("Hello"); 2 final JButton button = new JButton("Click me!"); 3 button.addActionListener(new ActionListener() { 4 @Override 5 public void actionPerformed(final ActionEvent e) { 6 showMessageDialog(frame, "Hello, world!"); 7 } 8 }); 9 frame.add(b); 10 frame.pack(); 11 frame.setDefaultCloseOperation(DISPOSE_ON_CLOSE); 12 frame.setVisible(true); Single Method Callback Java 5 Anonymous Class
  • 51.
    1 final JFrameframe = new JFrame("Hello"); 2 final JButton button = new JButton("Click me!"); 3 button.addActionListener(e -> 4 5 6 showMessageDialog(frame, "Hello, world!") 7 8 ); 9 frame.add(b); 10 frame.pack(); 11 frame.setDefaultCloseOperation(DISPOSE_ON_CLOSE); 12 frame.setVisible(true); Single Method Callback Java 8 Expression Lambda
  • 52.
    Java 8 InstanceMethod References 1 public class Application { 2 Application() { 3 final JMenuItem open = new JMenuItem("Open..."); 4 final JMenuItem save = new JMenuItem("Save"); 5 open.addActionListener(this::open); 6 save.addActionListener(this::save); 7 } 8 private void open(final ActionEvent e) { 9 // ... 10 } 11 private void save(final ActionEvent e) { 12 // ... 13 } 14 }
  • 53.
    Java 8 Stream.forEach() 1import java.io.*; 2 import static java.lang.System.*; 3 4 public class Sort { 5 private static BufferedReader getIn() { 6 return new BufferedReader(new InputStreamReader(in)); 7 } 8 public static void main(final String... args) throws IOException { 9 try (final BufferedReader in = getIn()) { 10 in.lines().sorted().forEach(out::println); 11 } 12 } 13 }
  • 54.
    What if youwant to reuse A without B? Dependency Inversion Principle Component A Component B
  • 55.
    What if youwant to reuse A without B? Dependency Inversion Principle Component A Component B Sort Article
  • 56.
    What if youwant to reuse A without B? Dependency Inversion Principle Component A Component B Sort ArticleComparable
  • 57.
    Higher Order Functions Area form of polymorphism Serve the Dependency Inversion Principle Decouple software entities Make software entities reusable
  • 58.
    Higher-Order Functions andOO Higher-Order Functions can always be expressed using Objects. Not every expression using Objects is also a Higher-Order Function. I recommend to avoid calling methods that have Methods with side-effects as parameters or return values “Higher-Order Functions”.
  • 59.
    Higher-Order Functions References Higher-order function(Wikipedia) How is dependency inversion related to higher-order functions? (StackExchange)
  • 60.
  • 61.
    Find Even Numbers Doubleit Sum it up public int calculate() { int[] numbers = {1, 5, 10, 9, 12}; List<Integer> doubledEvenNumbers = new ArrayList<>(); for (int number : numbers) if (number % 2 == 0) doubleEvenNumbers.add(num * 2); int total = 0; for (int even : doubleEvenNumbers) total = total + even; return total; } Imperative Style
  • 62.
    Declarative Style val list= List(1, 5, 10, 9, 12) val total = list.filter( number => number % 2 == 0) .map ( evenNumber => evenNumber * 2) .sum
  • 63.
    Imperative Paradigm How todo it Mutability Use locking / synchronization for thread safety Side effects null values
  • 64.
    Declarative Paradigm What todo Immutability No loops (recursion)
  • 65.
  • 66.
    Get popcorn, leanback, relax and enjoy If you know Git internals
  • 67.
    Now listen carefullyand learn something about Git at the same time! If you do not know Git internals
  • 68.
    “All fields final”- even in data structures. Previous version is preserved. Modifying data structures actually creates copies of modified parts, references of unmodified parts. Persistent Data Structure
  • 69.
    Three Levels ofPersistence 1.Partially Persistent Query all versions Update only latest version 2.Fully Persistent Query all versions Update all versions 3.Confluently Persistent Combinators -> Directed Acyclic Graph
  • 70.
    Immutable (Persistent) Object 1class Point { 2 final int x; 3 final int y; 4 Point(final int x, final int y) { 5 this.x = x; 6 this.y = y; 7 } 8 }
  • 71.
    Persistent Data Structures:List 1 public class ListNode<T> { 2 public final ListNode<T> next; 3 public final T data; 4 public ListNode(final T data) { this(null, data); } 5 public ListNode(final ListNode<T> next, final T data) { 6 this.next = next; 7 this.data = data; 8 } 9 }
  • 72.
  • 73.
    Persistent Data Structures:List fedcba c’b’a’
  • 74.
    Persistent Data Structures:Tree 1 public class TreeNode<T> { 2 public final TreeNode<T> left; 3 public final TreeNode<T> right; 4 public final T data; 5 public TreeNode(final T data) {this(null, null, data);} 6 TreeNode(TreeNode<T> left, TreeNode<T> right, T data) { 7 this.left = left; 8 this.right = right; 9 this.data = data; 10 } 11 }
  • 75.
    Persistent data structure(Wikipedia) Data Structures (Clojure) Persistent Data Structures References
  • 76.
  • 78.
  • 79.
    int x =5 * 3; System.out.println(x); int x = product(2); System.out.println(x); public int product(int num) { System.out.println("product method"); return num * 3; } product method 6
  • 80.
    Evaluate immediately atthe time of assignment Call By Value Call By Reference Strict Evaluation
  • 81.
    multiply(true, 10 /0); int multiply(boolean flag, int i) { if (flag) return 100; else return i * 5; } // → Division by zero
  • 82.
  • 83.
    Function parameter assignment Variableassignment 2 types of assignments
  • 84.
    val result =product(true, 10/0) println(result) def product(flag: => Boolean, num: => Int) = { if (flag) 100 else 5 * num } // → 100
  • 85.
    Call By Name(Function Parameters) Call By Need (Variables) Call By Need = Lazy Evaluation Non Strict Evaluation
  • 86.
    public class Singleton{ private static Singleton instance = null; private Singleton() {} public static Singleton getInstance() { if (instance == null) { System.out.println("Create new for the first time."); instance = new Singleton(); } return instance; } public static void main(final String... args) { Singleton.getInstance(); Singleton.getInstance(); } }
  • 87.
    lazy val result= func("Hello") println("333") println(result) println(result) def func(str: String) = { println("Inside func") str + ", World!" } 333 Inside func Hello, World! Hello, World!
  • 88.
    Avoids unnecessary computation →More Performance Evaluates only once → More Performance Infinite Data Structures (Streams) Why Lazy Evaluation?
  • 89.
    Lazy Description of OddNumbers lazy 1 lazy 3 lazy 5 lazy 7 lazy 9 So on … 1 3 5 7 9 So on …
  • 90.
    Avoids unnecessary computation →More Performance Infinite Data Structures (Streams) Modularity Why Lazy Evaluation?
  • 91.
    Haskell By default NonStrict Evaluation
  • 92.
  • 93.
    𝑓 : ℕ0× ℕ0 → ℕ0 𝑓(𝑥, 𝑦) = 𝑥 + 𝑦 Defined ∀ 𝑥: 𝑥 ∊ ℕ0 ⇒ Total Function Partial Functions in Mathematics typedef uint32_t u32; u32 f(u32 x, u32 y) { return x + y; }
  • 94.
    𝑓 : ℕ0× ℕ0 → ℕ0 𝑓(𝑥, 𝑦) = 𝑥 + 𝑦 Defined ∀ 𝑥: 𝑥 ∊ ℕ0 ⇒ Total Function 𝑓 : ℕ0 × ℕ0 → ℕ0 𝑓(𝑥, 𝑦) = 𝑥 − 𝑦 Only when 𝑥 ≥ 𝑦 ⇒ Partial Function Partial Functions in Mathematics typedef uint32_t u32; u32 f(u32 x, u32 y) { return x + y; } u32 f(u32 x, u32 y) { return x - y; }
  • 95.
    Partial Functions inScala val isEven: PartialFunction[Int, String] = { case x if x % 2 == 0 => x + "is even" } val isOdd: PartialFunction[Int, String] = { case x if x % 2 == 1 => x + "is odd" } val sample = 1 to 10 val evenNumbers = sample collect isEven val numbers = sample map (isEven orElse isOdd)
  • 96.
    Partial Functions “You almostnever have an excuse for writing a partial function!” - Haskell Wiki
  • 97.
    Partial Functions References Partial Function(Wikipedia) Partial Functions (Haskell Wiki) PartialFunction (Scala API)
  • 98.
  • 99.
    float x, y,z; y = g(x); z = f(y); z = f(g(x));
  • 100.
    “Function Composition” isapplying one function to the results of another. Haskell foo = f . g Scala val add = (x: Int) => x + 10 val subtract = (x: Int) => x - 5 List(10, 20, 30).map(add and Then subtract) First Class Composition
  • 101.
  • 102.
    “Currying is similarto the process of calculating a function of multiple variables for some given values on paper.” - Wikipedia Currying
  • 103.
    Currying for thepoor: Method Overloading class Complex { final double real; final double imaginary; Complex(double real, double imaginary) { this.real = real; this.imaginary = imaginary; } static Complex real(double real) { return new Complex(real, 0); } }
  • 104.
    Formal Definition ofCurrying Given a function f of type f : (X × Y) → Z, currying it makes a function curry(f): X → (Y → Z) That is, curry(f) takes an argument of type X and returns a function of type Y → Z.
  • 105.
    Currying in Scala defadd(x: Int, y: Int) = x + y add(1, 2) // 3 add(7, 3) // 10 def add(x: Int)(y: Int) = x + y add(1)(2) // 3 add(7)(3) // 10
  • 106.
    Currying existing Functions defadd(x: Int, y: Int) = x + y val addCurried = Function.curried(add _) add(1, 2) // 3 addCurried(1)(2) // 3
  • 107.
    Currying (Wikipedia) Function Curryingin Scala (Code Commit) Currying References
  • 108.
  • 109.
    Images used maybe subject to copyright. Use in this presentation on the basis of fair use for the purpose of teaching and education. References
  • 110.
    Backup Slides follow Notpart of the presentation
  • 111.
    Reducing the TransformationPriority Premise for Functional Programming Functional Programming and TPP
  • 112.
    Original {} → nil nil→ constant constant → constant+ constant → scalar statement → statements unconditional → if scalar → array array → container statement → recursion if → while expression → function variable → assignment Transformation Priority Premise Functional {} → nil nil → constant constant → constant+ n/a statement → statements unconditional → if scalar → list n/a statement → recursion n/a (use recursion) expression → function n/a
  • 113.
  • 114.
    main(Argv) :- echo(Argv). echo([]):- nl. echo([Last]) :- write(Last), echo([]). echo([H|T]) :- write(H), write(' '), echo(T). Echo in Prolog
  • 115.
    qsort :: (Orda) => [a] -> [a] qsort [] = [] qsort (x:xs) = let left = qsort [a | a <- xs, a <= x] right = qsort [a | a <- xs, a > x] in left ++ [x] ++ right --or even shorter qsort (x:xs) = qsort [a | a <- xs, a <= x] ++ [x] ++ qsort [a | a <- xs, a > x] Quicksort in Haskell
  • 116.
    Quicksort in Perl5 sub qsort { return @_ if @_ < 2; my $p = splice @_, int rand @_, 1; qsort(grep$_<$p,@_), $p, qsort(grep$_>=$p,@_); }
  • 117.
    Quicksort in Scala defqsort[T](list: List[T])(implicit ev1: T => Ordered[T]): List[T] = list match { case Nil => Nil case p :: xs => val (lesser, greater) = xs partition (_ <= p) qsort(lesser) ++ List(p) ++ qsort(greater) }
  • 118.
  • 120.
    f(x) = 2x2- 2x + 3
  • 121.
    f(x) = 2x2- 2x + 3 f(4) = 2*4*4 - 2*4 + 3 = 32 - 14 + 3 = 27 The value of x will never change inside a mathematical function. Same input, same output - all the time! Call f() multiple times, without any side-effects. We don’t have to recalculate f(4), replace occurrence of f(4) with 27 (Referential Transparency)
  • 122.
    public class Account{ int balance; public Account(int balance) { this.balance = balance; } public int credit(int amount) { return balance += amount; } } Account account = new Account(100); account.credit(500); // → balance == 600 account.credit(500); // → balance == 1100
  • 123.
    public class Account{ final int balance; public Account(int balance) { this.balance = balance; } public Account credit(int amount) { return new Account(balance + amount); } } Account account = new Account(100); Account currentAccountState = account.credit(500); Account newAccountState = currentAccountState.credit(500); account.credit(500); // → currentAccount(600)
  • 126.
    public int calculate(){ int[] numbers = {1, 5, 10, 9, 12}; List<Integer> doubledEvenNumbers = new ArrayList<>(); int total = c; for (int number : numbers) if (number % 2 == 0) total += num * 2; return total; } Imperative Style
  • 127.
    Declarative Style public intcalculate() { return IntStream.of(1, 5, 10, 9, 12) .filter(number -> number % 2 == 0) .map(number -> number * 2) .sum(); }
  • 128.
    Declarative Style def calculate(){ List(1, 5, 10, 9, 12) .filter(number => number % 2 == 0) .map(number => number * 2) .sum }
  • 129.
    public int product(intnum) { System.out.println("product method"); return num * 3; } int x = 5 * 3; System.out.println(x); x = product(2); System.out.println(x); 15 product method 6
  • 130.
    int multiply(boolean flag,int i) { if (flag) return 100; else return i * 5; } System.out.println(multiply(true, 10 / 0)); // → Division by zero
  • 131.
    public class Singleton{ private Singleton() { System.out.println("Create new for the first time."); } public static Singleton getInstance() { return LazyHolder.INSTANCE; } private static class LazyHolder { private static final Singleton INSTANCE = new Singleton(); } }
  • 132.
    public class Singleton{ public static final Singleton INSTANCE = new Singleton(); private Singleton() { System.out.println("Init"); } }
  • 133.
    public enum Singleton{ INSTANCE; private Singleton() { System.out.println("Init"); } }