0
by Mario Fusco
mario.fusco@gmail.com
twitter: @mariofusco
Moore's
law
The number of transistors on integrated
circuits doubles approximately every two years
Moore's
law
The number of transistors on integrated
circuits doubles approximately every two years
Now achieved
by increas...
Moore's
law
The number of transistors on integrated
circuits doubles approximately every two years
Now achieved
by increas...
Fortran
C / C++
Java
Lisp
ML
Haskell
Add abstractions
C#
Algol
Subtract abstractions
Imperative languages
Functional langu...
Amdahl's
law
The speedup of a program using multiple processors
in parallel computing is limited by the time needed
for th...
Concurrency & Parallelism
Parallel programming
Running multiple tasks at
the same time
Concurrent programming
Managing con...
The cause of the problem …
Mutable state +
Parallel processing =
Non-determinism
The cause of the problem …
Mutable state +
Parallel processing =
Non-determinism
Functional
Programming
Race conditions
Deadlocks
Starvation
Livelocks
… and its effects
Too hard to think about them!
Race conditions
Deadlocks
Starvation
Livelocks
… and its effects
The native Java concurrency model
Based on:
They are sometimes plain evil …
… and sometimes a necessary pain …
… but alway...
Different concurrency models
Isolated mutable state (actors)
Purely immutable (pure functions)
Shared mutable state
(threa...
Summing attendants ages (Threads)
class Blackboard {
int sum = 0;
int read() { return sum; }
void write(int value) { sum =...
Summing attendants ages (Actors)
class Blackboard extends UntypedActors {
int sum = 0;
public void onReceive(Object messag...
Summing attendants ages (Functional)
class Blackboard {
final int sum;
Blackboard(int sum) { this.sum = sum; }
}
class Att...
The state quadrants
Mutable
Immutable
Shared
Unshared
Actors
Functional
Programming
Threads
Concurrency friendly
Concurren...
OOP makes code understandable
by encapsulating moving parts
FP makes code understandable
by minimizing moving parts
- Mich...
The OOP/FP dualism - OOP
public class Bird { }
public class Cat {
private Bird catch;
private boolean full;
public void ca...
The OOP/FP dualism - FP
public class Bird { }
public class Cat {
public CatWithCatch capture(Bird bird) { return new CatWi...
The OOP/FP dualism - FP
public class Bird { }
public class Cat {
public CatWithCatch capture(Bird bird) { return new CatWi...
for (Employee e : employees) {
e.setSalary(e.getSalary() * 1.03);
}
employees.forEach(e -> e.setSalary(e.getSalary() * 1.0...
Encourages a pipelined ( "fluent" ) usage style
Operations are divided between intermediate and terminal
Lazy in nature: o...
Encourages a pipelined ( "fluent" ) usage style
Operations are divided between intermediate and terminal
Lazy in nature: o...
Is there such thing as a free lunch?
Probably yes …
… but we need functional
forks and knives to eat it
Reassigning a variable
Modifying a data structure in place
Setting a field on an object
Throwing an exception or halting w...
What is a (pure) function?
A function with input type A and output type B
is a computation which relates every value a of
...
Referential transparency
An expression e is referentially transparent if for all programs p,
all occurrences of e in p can...
RT
String x = "purple";
String r1 = x.replace('p', 't');
String r2 = x.replace('p', 't');
String r1 = "purple".replace('p'...
RT wins
Under a developer point of view:
Easier to reason about since effects of evaluation are
purely local
Use of the su...
Mutability
Parameter binding is about assigning names to things
Mutating variables is about assigning things to names
Does...
Immutability
Immutable objects can be shared among
many threads exactly because none of
them can modify it
In the same way...
5
8
7 9
3
4
EEEEE E
E
Persistent Collections
5
8
7 9
3
4
EEEEE E
E
2
Persistent Collections
5
8
7 9
3
4
EEEEE E
E
5
3
2
EE
Persistent Collections
5
8
7 9
3
4
EEEEE E
E
5
3
2
EE
Shared data
Old Root
New Root
Persistent Collections
Modularity
class Player {
String name;
int score;
}
public void declareWinner(Player p) {
System.out.println(p.name + " wi...
Modularity
class Player {
String name;
int score;
}
public void declareWinner(Player p) {
System.out.println(p.name + " wi...
Modularity
class Player {
String name;
int score;
}
public void declareWinner(Player p) {
System.out.println(p.name + " wi...
A pure functional core
functional
core
Any function with side-effects can be split into a pure function at the
core and a ...
Key Takeaways
Strive for immutability
Confine side-effects
Avoid blocking code
Cede control with higher-order functions
Le...
Mario Fusco
Red Hat – Senior Software Engineer
mario.fusco@gmail.com
twitter: @mariofusco
Q A
Thanks … Questions?
If You Think You Can Stay Away from Functional Programming, You Are Wrong
Upcoming SlideShare
Loading in...5
×

If You Think You Can Stay Away from Functional Programming, You Are Wrong

3,081

Published on

Published in: Technology
2 Comments
13 Likes
Statistics
Notes
  • Best deck I've seen in a long time.
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • Succinct historical treatment of this inevitable trend.
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
No Downloads
Views
Total Views
3,081
On Slideshare
0
From Embeds
0
Number of Embeds
2
Actions
Shares
0
Downloads
69
Comments
2
Likes
13
Embeds 0
No embeds

No notes for slide

Transcript of "If You Think You Can Stay Away from Functional Programming, You Are Wrong"

  1. 1. by Mario Fusco mario.fusco@gmail.com twitter: @mariofusco
  2. 2. Moore's law The number of transistors on integrated circuits doubles approximately every two years
  3. 3. Moore's law The number of transistors on integrated circuits doubles approximately every two years Now achieved by increasing the number of cores
  4. 4. Moore's law The number of transistors on integrated circuits doubles approximately every two years Now achieved by increasing the number of cores
  5. 5. Fortran C / C++ Java Lisp ML Haskell Add abstractions C# Algol Subtract abstractions Imperative languages Functional languages Scala F# Hybrid languages
  6. 6. Amdahl's law The speedup of a program using multiple processors in parallel computing is limited by the time needed for the sequential fraction of the program
  7. 7. Concurrency & Parallelism Parallel programming Running multiple tasks at the same time Concurrent programming Managing concurrent requests Both are hard!
  8. 8. The cause of the problem … Mutable state + Parallel processing = Non-determinism
  9. 9. The cause of the problem … Mutable state + Parallel processing = Non-determinism Functional Programming
  10. 10. Race conditions Deadlocks Starvation Livelocks … and its effects
  11. 11. Too hard to think about them! Race conditions Deadlocks Starvation Livelocks … and its effects
  12. 12. The native Java concurrency model Based on: They are sometimes plain evil … … and sometimes a necessary pain … … but always the wrong default Threads Semaphores SynchronizationLocks
  13. 13. Different concurrency models Isolated mutable state (actors) Purely immutable (pure functions) Shared mutable state (threads + locks)
  14. 14. Summing attendants ages (Threads) class Blackboard { int sum = 0; int read() { return sum; } void write(int value) { sum = value; } } class Attendant implements Runnable { int age; Blackboard blackboard; public void run() { synchronized(blackboard) { int oldSum = blackboard.read(); int newSum = oldSum + age; blackboard.write(newSum); } } }
  15. 15. Summing attendants ages (Actors) class Blackboard extends UntypedActors { int sum = 0; public void onReceive(Object message) { if (message instanceof Integer) { sum += (Integer)message; } } } class Attendant { int age; Blackboard blackboard; public void sendAge() { blackboard.sendOneWay(age); } }
  16. 16. Summing attendants ages (Functional) class Blackboard { final int sum; Blackboard(int sum) { this.sum = sum; } } class Attendant { int age; Attendant next; public Blackboard addMyAge(Blackboard blackboard) { final Blackboard b = new Blackboard(blackboard.sum + age); return next == null ? b : next.myAge(b); } }
  17. 17. The state quadrants Mutable Immutable Shared Unshared Actors Functional Programming Threads Concurrency friendly Concurrency unfriendly
  18. 18. OOP makes code understandable by encapsulating moving parts FP makes code understandable by minimizing moving parts - Michael Feathers OOP vs FP
  19. 19. The OOP/FP dualism - OOP public class Bird { } public class Cat { private Bird catch; private boolean full; public void capture(Bird bird) { catch = bird; } public void eat() { full = true; catch = null; } } Cat cat = new Cat(); Bird bird = new Bird(); cat.capture(bird); cat.eat(); The story
  20. 20. The OOP/FP dualism - FP public class Bird { } public class Cat { public CatWithCatch capture(Bird bird) { return new CatWithCatch(bird); } } public class CatWithCatch { private final Bird catch; public CatWithCatch(Bird bird) { catch = bird; } public FullCat eat() { return new FullCat(); } } public class FullCat { } BiFunction<Cat, Bird, FullCat> story = ((BiFunction<Cat, Bird, CatWithCatch>)Cat::capture) .compose(CatWithCatch::eat); FullCat fullCat = story.apply( new Cat(), new Bird() );
  21. 21. The OOP/FP dualism - FP public class Bird { } public class Cat { public CatWithCatch capture(Bird bird) { return new CatWithCatch(bird); } } public class CatWithCatch { private final Bird catch; public CatWithCatch(Bird bird) { catch = bird; } public FullCat eat() { return new FullCat(); } } public class FullCat { } BiFunction<Cat, Bird, FullCat> story = ((BiFunction<Cat, Bird, CatWithCatch>)Cat::capture) .compose(CatWithCatch::eat); FullCat fullCat = story.apply( new Cat(), new Bird() ); Immutability Emphasis on verbs instead of names No need to test internal state: correctness enforced by the compiler
  22. 22. for (Employee e : employees) { e.setSalary(e.getSalary() * 1.03); } employees.forEach(e -> e.setSalary(e.getSalary() * 1.03)); ̶ Inherently serial ̶ Client has to manage iteration ̶ Nested loops are poorly readable + Library is in control opportunity for internal optimizations as parallelization, lazy evaluation, out-of-order execution + More what, less how better readability + Fluent (pipelined) operations better readability + Client can pass behaviors into the API as data possibility to abstract and generalize over behavior more powerful, expressive APIs Not only a syntactic change! Internal vs External Iteration
  23. 23. Encourages a pipelined ( "fluent" ) usage style Operations are divided between intermediate and terminal Lazy in nature: only terminal operations actually trigger a computation employees.stream() .filter(e -> e.getIncome() > 50000) .map(e -> e.getName()) .forEach(System.out::println); Streams - Efficiency with laziness
  24. 24. Encourages a pipelined ( "fluent" ) usage style Operations are divided between intermediate and terminal Lazy in nature: only terminal operations actually trigger a computation employees.stream() .filter(e -> e.getIncome() > 50000) .map(e -> e.getName()) .forEach(System.out::println); parallelStream() … and parallelism for free Streams - Efficiency with laziness
  25. 25. Is there such thing as a free lunch?
  26. 26. Probably yes … … but we need functional forks and knives to eat it
  27. 27. Reassigning a variable Modifying a data structure in place Setting a field on an object Throwing an exception or halting with an error Printing to the console Reading user input Reading from or writing to a file Drawing on the screen A program created using only pure functions What is a functional program? No side effects allowed like: Functional programming is a restriction on how we write programs, but not on what they can do } }
  28. 28. What is a (pure) function? A function with input type A and output type B is a computation which relates every value a of type A to exactly one value b of type B such that b is determined solely by the value of a But, if it really is a function, it will do nothing else
  29. 29. Referential transparency An expression e is referentially transparent if for all programs p, all occurrences of e in p can be replaced by the result of evaluating e, without affecting the observable behavior of p A function f is pure if the expression f(x) is referentially transparent for all referentially transparent x
  30. 30. RT String x = "purple"; String r1 = x.replace('p', 't'); String r2 = x.replace('p', 't'); String r1 = "purple".replace('p', 't'); r1: "turtle" String r2 = "purple".replace('p', 't'); r2: "turtle" StringBuilder x = new StringBuilder("Hi"); StringBuilder y = x.append(", mom"); String r1 = y.toString(); String r2 = y.toString(); String r1 = x.append(", mom").toString(); r1: "Hi, mom" String r2 = x.append(", mom").toString(); r1: "Hi, mom, mom" Non-RT vs.
  31. 31. RT wins Under a developer point of view: Easier to reason about since effects of evaluation are purely local Use of the substitution model: it's possible to replace a term with an equivalent one Under a performance point of view: The JVM is free to optimize the code by safely reordering the instructions No need to synchronize access to shared data Possible to cache the result of time consuming functions (memoization), e.g. with Map.computeIfAbsent(K key, Function<? super K,? extends V> mappingFunction)
  32. 32. Mutability Parameter binding is about assigning names to things Mutating variables is about assigning things to names Does that second one sound weird? … well it's because it IS weird
  33. 33. Immutability Immutable objects can be shared among many threads exactly because none of them can modify it In the same way immutable (persistent) data structures can be shared without any need to synchronize the different threads accessing them
  34. 34. 5 8 7 9 3 4 EEEEE E E Persistent Collections
  35. 35. 5 8 7 9 3 4 EEEEE E E 2 Persistent Collections
  36. 36. 5 8 7 9 3 4 EEEEE E E 5 3 2 EE Persistent Collections
  37. 37. 5 8 7 9 3 4 EEEEE E E 5 3 2 EE Shared data Old Root New Root Persistent Collections
  38. 38. Modularity class Player { String name; int score; } public void declareWinner(Player p) { System.out.println(p.name + " wins!"); } public void winner(Player p1, Player p2) { if (p1.score > p2.score) declareWinner(p1) else declareWinner(p2); }
  39. 39. Modularity class Player { String name; int score; } public void declareWinner(Player p) { System.out.println(p.name + " wins!"); } public void winner(Player p1, Player p2) { if (p1.score > p2.score) declareWinner(p1) else declareWinner(p2); } public Player maxScore(Player p1, Player p2) { return p1.score > p2.score ? p1 : p2; } public void winner(Player p1, Player p2) { declareWinner(maxScore(p1, p2)); } Separate computational logic from side effects
  40. 40. Modularity class Player { String name; int score; } public void declareWinner(Player p) { System.out.println(p.name + " wins!"); } public void winner(Player p1, Player p2) { if (p1.score > p2.score) declareWinner(p1) else declareWinner(p2); } public Player maxScore(Player p1, Player p2) { return p1.score > p2.score ? p1 : p2; } public void winner(Player p1, Player p2) { declareWinner(maxScore(p1, p2)); } Separate computational logic from side effects declareWinner(players.reduce(maxScore).get()) reuse maxScore to compute the winner among a list of players
  41. 41. A pure functional core functional core Any function with side-effects can be split into a pure function at the core and a pair of functions with side-effect. This transformation can be repeated to push side-effects to the outer layers of the program.
  42. 42. Key Takeaways Strive for immutability Confine side-effects Avoid blocking code Cede control with higher-order functions Leverage referential transparency Use FP to design more composable and reusable API … but there are no dogmas Be pragmatic and use the right tool for the job at hand Poly-paradigm programming is more powerful and effective than polyglot programming
  43. 43. Mario Fusco Red Hat – Senior Software Engineer mario.fusco@gmail.com twitter: @mariofusco Q A Thanks … Questions?
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×