Webinar: The Art of Prioritizing Your Product Roadmap by AWS Sr PM - Tech
Functional Programming with Immutable Data Structures
1. Functional Programming with
Immutable Data Structures
Why Imperative Languages are
Fundamentally Broken in a
Multi-Threaded Environment
Ivar Thorson
Italian Institute of Technology
November 2, 2010
26. Goal is to convince you that
1. shared mutable data is now a
philosophically bankrupt idea.
27. Goal is to convince you that
1. shared mutable data is now a
philosophically bankrupt idea.
2. code and data should be structured as
trees
28. Goal is to convince you that
1. shared mutable data is now a
philosophically bankrupt idea.
2. code and data should be structured as
trees
3. OOP isn’t the best way to achieve
OOP’s goals
97. The Most Important Slide
x is a name, an identity of a sequence of
values
98. The Most Important Slide
x is a name, an identity of a sequence of
values
x has different values at different times
99. The Most Important Slide
x is a name, an identity of a sequence of
values
x has different values at different times
The values of x are related by pure
functions
100. The Most Important Slide
x is a name, an identity of a sequence of
values
x has different values at different times
The values of x are related by pure
functions
In this case, by the increment function
103. The idea of a variable confuses identity and
the most current value!
115. The old values of the data are kept and
indexed by time
116. The old values of the data are kept and
indexed by time
Data is immutable once created – we
cannot/will not change it!
117. The old values of the data are kept and
indexed by time
Data is immutable once created – we
cannot/will not change it!
Values only destroyed when unneeded
121. (a b c) + d = (a b c d)
What if the input and output shared
structure?
122. (a b c) + d = (a b c d)
What if the input and output shared
structure?
Sharing structure is dangerous for
mutable data
123. (a b c) + d = (a b c d)
What if the input and output shared
structure?
Sharing structure is dangerous for
mutable data
...but sharing structure is safe if the
data is immutable.
133. Advantages of immutable trees:
No locking required
No ’stopping the world’ to see (readers
don’t block writers)
134. Advantages of immutable trees:
No locking required
No ’stopping the world’ to see (readers
don’t block writers)
Worldview never becomes corrupted
135. Advantages of immutable trees:
No locking required
No ’stopping the world’ to see (readers
don’t block writers)
Worldview never becomes corrupted
Minimizes memory use while
maintaining multiple copies
136. Advantages of immutable trees:
No locking required
No ’stopping the world’ to see (readers
don’t block writers)
Worldview never becomes corrupted
Minimizes memory use while
maintaining multiple copies
Unused nodes are garbage-collected
137. We’ve gone a long way, but we’re only half
way to real concurrency
139. Immutability lets us read concurrently, but
not write concurrently to a single piece of
data
142. How can we coordinate the actions of
different threads working on the same data
at the same time?
143. ”Treat changes in an identity’s value as a
database transaction.” – Rich Hickey
154. For even more concurrency:
Sometimes you don’t care about the
order of function application
155. For even more concurrency:
Sometimes you don’t care about the
order of function application
Commutative writers won’t need to retry
156. For even more concurrency:
Sometimes you don’t care about the
order of function application
Commutative writers won’t need to retry
Writers don’t interfere with other
writers!
167. Variables couldn’t do this because:
Confuse identity and values
Are mutable and can be corrupted
168. Variables couldn’t do this because:
Confuse identity and values
Are mutable and can be corrupted
Assume a single thread of control, no
interruptions
169. Variables couldn’t do this because:
Confuse identity and values
Are mutable and can be corrupted
Assume a single thread of control, no
interruptions
Maintain only the last written copy
208. Why lispers go nuts:
Macros in lisp are far more powerful
than in other languages.
209. Why lispers go nuts:
Macros in lisp are far more powerful
than in other languages.
You can build new constructs that are
just as legitimate as existing constructs
like if
210. Why lispers go nuts:
Macros in lisp are far more powerful
than in other languages.
You can build new constructs that are
just as legitimate as existing constructs
like if
You can abstract away boilerplate code
213. Aside
If Java used parentheses properly, XML
wouldn’t exist
Lisp parentheses describe structure
214. Aside
If Java used parentheses properly, XML
wouldn’t exist
Lisp parentheses describe structure
Most languages use ad-hoc syntax, data
formats
215. Aside
If Java used parentheses properly, XML
wouldn’t exist
Lisp parentheses describe structure
Most languages use ad-hoc syntax, data
formats
Simplicity is elegance
221. Hard-to-show Examples
When you type (, emacs adds the )
Indentation is automatic
You can easily navigate heirarchically
222. Hard-to-show Examples
When you type (, emacs adds the )
Indentation is automatic
You can easily navigate heirarchically
Take next three expressions, apply them
to a function
224. Summary of Lisp Parentheses
Parentheses render explicit the
tree-structure of your program
225. Summary of Lisp Parentheses
Parentheses render explicit the
tree-structure of your program
Homoiconicity lets you write programs
with programs
226. Summary of Lisp Parentheses
Parentheses render explicit the
tree-structure of your program
Homoiconicity lets you write programs
with programs
Structural Editing is fun and easy
241. The fundamental mechanism of OOP – the
inheritance of data, interfaces, type, or
methods from a parent – is often more
difficult to use in practice than techniques
that use functions to achieve the same effect.
245. Implementation inheritance is bad:
Forces “is-a” relationship instead of
“has-a”, and “has-a” is almost always
better
246. Implementation inheritance is bad:
Forces “is-a” relationship instead of
“has-a”, and “has-a” is almost always
better
Heirarchical nominalization is difficult
247. Implementation inheritance is bad:
Forces “is-a” relationship instead of
“has-a”, and “has-a” is almost always
better
Heirarchical nominalization is difficult
Changes to a class affect all the
subclasses
255. Problems
What happens if we want to make a ball
that both rolls and bounces?
Do/Can we inherit from both?
256. Problems
What happens if we want to make a ball
that both rolls and bounces?
Do/Can we inherit from both?
What if our ball cracks and loses its
bounciness?
257. Problems
What happens if we want to make a ball
that both rolls and bounces?
Do/Can we inherit from both?
What if our ball cracks and loses its
bounciness?
Is a non-round rugby ball a subclass of
ball too?
260. Interfaces are Simpler
Define functional interfaces, but don’t
inherit the implementation
If you want to use another object’s
function to accomplish a task, just use it
261. Interfaces are Simpler
Define functional interfaces, but don’t
inherit the implementation
If you want to use another object’s
function to accomplish a task, just use it
No need to encapsulate their function in
an object
262. Interfaces are Simpler
Define functional interfaces, but don’t
inherit the implementation
If you want to use another object’s
function to accomplish a task, just use it
No need to encapsulate their function in
an object
Multiple interfaces are simpler than
multiple inheritance
263. FREE THE VERBS!! Separate your object
methods from your objects!
267. Making Drum Noises
Drum, cymbal and stick classes
When I hit something with the stick, it
makes a noise
268. Making Drum Noises
Drum, cymbal and stick classes
When I hit something with the stick, it
makes a noise
Single Dispatch:
drum.makeNoise(drumstick)
269. Making Drum Noises
Drum, cymbal and stick classes
When I hit something with the stick, it
makes a noise
Single Dispatch:
drum.makeNoise(drumstick)
cymbal.makeNoise(drumstick)
288. Part 3 Conclusion
Polymorphism is better done through
interfaces than subtype inheritance.
Functions do not require a heirarchy
289. Part 3 Conclusion
Polymorphism is better done through
interfaces than subtype inheritance.
Functions do not require a heirarchy
Functions allow simple multiple dispatch