purely functional data structures
TRANSCRIPT
Purely functionaldata structures
@tkaczmarzykblog.kaczmarzyk.net
Tomek “Kosior” Kaczmarzyk
meh...
?WAT!?
Achievement unlocked!WTF Level 3
whoami
Just wandering around the world, developing software
@tkaczmarzykblog.kaczmarzyk.net
Tomek “Kosior” Kaczmarzyk
Recently hired by Siili Solutions
“Bad programmers worry about the code.Good programmers worry aboutdata structures and their relationships.”
Linus Torvalds
public class DefensiveList<T> {
private List<T> values; public DefensiveList(List<T> values) { values = new ArrayList<>(values); }
public DefensiveList<T> add(T elem) { List<T> copy = new ArrayList<>(values); copy.add(elem); return new DefensiveList<T>(copy); }}
[1, 2, 3].head() = 1
[1, 2, 3].tail() = [2, 3]
[1, 2, 3].cons(7) = [7, 1, 2, 3]
[1, 2, 3].snoc(7) = [1, 2, 3, 7]
snoc(2)
{ [2], [] }
{ [], [] }
snoc(3)
{ [2], [3] }snoc(4)
{ [2], [4, 3] }snoc(5)
{ [2], [5, 4, 3] }
newList = mylist.snoc(3) .snoc(4) .tail() .snoc(5);
newList.tail();newList.tail();newList.tail();newList.tail();
class Suspension<T> { private Supplier<T> suspendedFun; private T calculatedValue; public Suspension(Supplier<T> suspendedFun) { this.suspendedFun = suspendedFun; } public T force() { if (calculatedValue == null) { calculatedValue = suspendedFun.get(); } return calculatedValue; }}
Suspension<Integer> memoizedRandom = new Suspension<>(() -> new Random().nextInt()); println(memoizedRandom.force()); // genereted here println(memoizedRandom.force()); // cached valueprintln(memoizedRandom.force()); // on subsequent calls
interface Stream<T> { Stream<T> tail(); Stream<T> append(Suspension<Stream<T>> other); Stream<T> reverse(); boolean isEmpty();}
interface Stream<T> { Stream<T> tail(); Stream<T> append(Suspension<Stream<T>> other); Stream<T> reverse(); boolean isEmpty();}
class Empty<T> implements Stream<T> {
public Stream<T> tail() { throw new UnsupportedOptionException(); }
public Stream<T> append(Suspension<Stream<T>> other){ return other.force(); }
public Stream<T> reverse() { return this; }
public boolean isEmpty() { return true; }}
class NonEmpty<T> implements Stream<T> { private T head; private Suspension<Stream<T>> tail;
public NonEmpty(T head, Suspension<Stream<T>> tail) { this.head = head; this.tail = tail; } public Stream<T> tail() { return tail.force(); }
public Stream<T> append(Suspension<Stream<T>> other) { return new NonEmpty<>( this.head, new Suspension<>(() -> this.tail().append(other))); }
public Stream<T> reverse() { // executes the full reverse... }
public boolean isEmpty() { return false; }}
class Queue<T> { private Stream<T> front; private int lenF; private Stream<T> rear; private int lenR; private Queue(Stream front, int lenF, Stream rear, int lenR){ // ordinary assignments... } public static <T> Queue<T> queue( Stream front, int lenF, Stream rear, int lenR){
if (lenR <= lenF) { return new Queue<T>(front, lenF, rear, lenR); } else return new Queue<T>( front.append(new Suspension<>(() -> rear.reverse())), lenF + lenR, new Empty<T>(), 0); }
public Queue<T> tail() { return queue(front.tail(), lenF - 1, rear, lenR); } }
Q {[5, 6, 7], []}
tail
tail
suspended reverse
is created here
tail tail
and forced here!
O(m)
at least
m x tail()
with O(1)
tail
tail tail tailat least
m x tail()
with O(1)
tail tail
tail tail
it's the same (==)
Suspension!
tail
tail
tail
tail tail tailat least
m x tail()
with O(1)
tail tail
tail tail
it's the same (==)
Suspension!
tail
tail
different Suspensionsbut each pays for m x O(1)
workingdirectory
repository
file A
file B
A1 B1snapshot1
snapshot2
B2
dir1
file C
snapshot3
A2
C1
(v2)
(v2)
100644 blob fa49b07797 fileA.txt100644 blob 1f7a7a472a fileB.txt040000 tree d8329fc1cc7 dir1
just a file!
commit tree da3b911d93889f6f35ddf4parent e78dca6f8f5e7dc825ded27094e0author Kosior <[email protected]>committer Kosior <[email protected]>
example commit :)
once again:just a text file!
recap
* immutability is powerful
* PF data structures can be damn effective!
* they can become a way to create legendary software :-)
Acknowledgements:“Purely functional data structures” by Chris Okasakihttp://git-scm.com/book
Photo credits:https://www.flickr.com/photos/jdhancock/9544541664/https://www.flickr.com/photos/janimut/14609601810/https://www.flickr.com/photos/macwagen/2819684/https://www.flickr.com/photos/matt_gibson/2580896289/https://www.flickr.com/photos/hktang/4243300265/https://www.flickr.com/photos/funfilledgeorgie/10922459733/https://www.flickr.com/photos/celinesphotographer/ 4044569502/https://www.flickr.com/photos/edsonhong1/5685375541/https://www.flickr.com/photos/ch-weidinger/17341905336/https://www.flickr.com/photos/toomuchdew/9284836919/