4. What makes up functional style?
• Functions, Closures, Lambdas, Blocks as
first-class citizens
• Higher order functions
• Mutable vs Immutable data structures
• Recursion
• Lazy vs Eager evaluation
• Declarative vs Imperative style
• Advanced Techniques
– Memoization, Trampolines, Composition and Curry
• Compile-time safety
• Concurrency
12. interface Calc {
def execute(n, m)
}
class CalcByMult implements Calc {
def execute(n, m) { n * m }
}
class CalcByManyAdds implements Calc {
def execute(n, m) {
def result = 0
n.times {
result += m
}
return result
}
}
def sampleData = [
[3, 4, 12],
[5, -5, -25]
]
Calc[] multiplicationStrategies = [
new CalcByMult(),
new CalcByManyAdds()
]
sampleData.each {data ->
multiplicationStrategies.each {calc ->
assert data[2] == calc.execute(data[0], data[1])
}
}
def multiplicationStrategies = [
{ n, m -> n * m },
{ n, m ->
def total = 0; n.times{ total += m }; total },
{ n, m -> ([m] * n).sum() }
]
def sampleData = [
[3, 4, 12],
[5, -5, -25]
]
sampleData.each{ data ->
multiplicationStrategies.each{ calc ->
assert data[2] == calc(data[0], data[1])
}
}
Language features instead of Patterns
(c)ASERT2006-2013
Strategy Pattern
with interfaces
with closures
19. Immutability
• An object’s value doesn’t change once created
• Examples
– Groovy has primitives & their wrapper classes,
Strings, null
– “constants” (final reference fields)
• With some caveats about what they point to
– Basic enum values
• With some caveats on complex enums
– Numerous (effectively) immutable classes
• java.awt.Color, java.net.URI, java.util.UUID, java.lang.Class,
java.util.Date, java.math.BigInteger, java.math.BigDecimal
– Your own carefully written classes
– Very careful use of aggregation/collection classes
– Special immutable aggregation/collection classes
20. Why Immutability?
• Simple
– Exactly one state
– Potentially easier to design, implement, use, reason
about & make secure
• Inherently referentially transparent
– Potential for optimisation
• Can be shared freely
– Including “constant” aggregations of immutables
– Including persistent structures of immutables
– Suitable for caching
– Can even cache “pure” expressions involving
immutables, e.g. 3 + 4, “string”.size(), fib(42)
– Inherently thread safe
24. Immutable practices
• Using mutating style
– We could possibly get away with this code here but it
has some debatable code smells
• (1) add a reference to a mutable list
• (2) change string reference losing original
• (3),(4) mutate list
• (4) duplicate first invention because original lost
String invention = 'Mouse Trap'
List inventions = [invention] //(1)
invention = 'Better ' + invention //(2)
inventions << invention //(3)
assert inventions == ['Mouse Trap', 'Better Mouse Trap']
inventions.removeAll 'Mouse Trap' //(4)
assert inventions == ['Better Mouse Trap']
26. Immutable practices
• Avoid using mutator methods
Avoid Prefer
list.sort() list.sort(false)
list.unique() list.unique(false)
list.reverse(true) list.reverse()
list.addAll list.plus
list.removeAll list.minus
String or List += or << use differently named variables
mutating java.util.Collections
void methods, e.g. shuffle, swap,
fill, copy, rotate
your own non mutating variants
27. Immutable practices
• Avoid using mutator methods
Avoid Prefer
list.sort() list.sort(false)
list.unique() list.unique(false)
list.reverse(true) list.reverse()
list.addAll list.plus
list.removeAll list.minus
String or List += or << use differently named variables
mutating java.util.Collections
void methods, e.g. shuffle, swap,
fill, copy, rotate
your own non mutating variants
public class Collections {
public static void shuffle(List<?> list) { /* ... */ }
/* ... */
}
28. Immutable practices
• Avoid using mutator methods
Avoid Prefer
list.sort() list.sort(false)
list.unique() list.unique(false)
list.reverse(true) list.reverse()
list.addAll list.plus
list.removeAll list.minus
String or List += or << use differently named variables
mutating java.util.Collections
void methods, e.g. shuffle, swap,
fill, copy, rotate
your own non mutating variants
static List myShuffle(List list) {
List result = new ArrayList(list)
Collections.shuffle(result)
result
}
37. Immutability – persistent collections
• You will see the correct results but in general, different
operations may give very differing performance
characteristics from what you expect
– But don’t fret, smart people are working on smart structures to support a variety
of scenarios. You may even have several in your current NoSQL implementation
A
B C
D E F G
H I
A*
C*
G*
KJ
original modified
38. Reality check
• OK, do I have to write this myself?
– Might pay to try some simple ones. Take a look at Eric
Lippert’s blog on some C# implementations. Here is
the first part (Part 1: Kinds of Immutability):
http://blogs.msdn.com/ericlippert/archive/2007/11/13/
immutability-in-c-part-one-kinds-of-immutability.aspx
– Also consider
• Part 2: Simple Immutable Stack, Part 3: Covariant Immutable
Stack, Part 4: Immutable Queue, Part 6: Simple Binary Tree
– There are probably plenty of implementations you can
already use
– See also: Purely Functional Data Structures by Chris
Okasak, Cambridge University Press (1999)
• It turns out you use trees for nearly everything!
39. Reality check
• Functional Java persistent data structures
– Singly-linked list (fj.data.List)
– Lazy singly-linked list (fj.data.Stream)
– Nonempty list (fj.data.NonEmptyList)
– Optional value (a container of length 0 or 1) (fj.data.Option)
– Immutable set using a red/black tree (fj.data.Set)
– Immutable multi-way tree (a.k.a. rose tree) (fj.data.Tree)
– Immutable tree-map using a red/black tree (fj.data.TreeMap)
– Products (tuples) of arity 1-8 (fj.P1..P8)
– Vectors of arity 2-8 (fj.data.vector.V2..V8)
– Pointed lists and trees (fj.data.Zipper and fj.data.TreeZipper)
– Type-safe, generic heterogeneous list (fj.data.hlist.HList)
– Immutable arrays (fj.data.Array)
– Disjoint union datatype (fj.data.Either)
– 2-3 finger trees supporting access to the ends in amortized O(1)
time (fj.data.fingertrees)
40. Reality check
• OK, have we achieved something simpler?
– It depends. Understanding the insides of persistent
data structures can be very hard
• But as you move towards more complex systems and more
concurrent systems, not having to worry about which
threads are mutating what and when usually outweighs the
complexities of using persistent data structures
• Arguing for impure in Haskell:
http://www.cse.unsw.edu.au/~benl/papers/thesis/lippmeier-
impure-world.pdf
– They still don’t solve all of the problems. For any
significant problem you will have multiple threads
working on the solution. In some sense we have just
moved the problem but at least we have separated
concerns.
• You might combine with message passing (actors) or
dataflow or software transactional memory (STM)
41. Immutable Classes
• Some Rules
– Don’t provide mutators
– Ensure that no methods can
be overridden
• Easiest to make the class final
• Or use static factories & non-public
constructors
– Make all fields final
– Make all fields private
• Avoid even public immutable constants
– Ensure exclusive access to any mutable components
• Don’t leak internal references
• Defensive copying in and out
– Optionally provide equals and hashCode methods
– Optionally provide toString method