SlideShare a Scribd company logo
1 of 40
Purely Functional
Data Structures in Scala
Vladimir Kostyukov
http://vkostyukov.ru
Agenda
• Immutability & Persistence
• Singly-Linked List
• Banker’s Queue
• Binary Search Tree
• Balanced BST: Red-Black Tree
• Scala support of these things
• Patricia Trie
• Hash Array Mapped Trie
2
Immutability & Persistence
Two problems:
• FP paradigm doesn’t support destructive updates
• FP paradigm expects both the old and new
versions of DS will be available after update
Two solutions:
• Immutable objects aren’t changeable
• Persistent objects support multiple versions
3
Singly-Linked List
4
35 7
Cons
Nil
abstract sealed class List {
def head: Int
def tail: List
def isEmpty: Boolean
}
case object Nil extends List {
def head: Int = fail("Empty list.")
def tail: List = fail("Empty list.")
def isEmpty: Boolean = true
}
case class Cons(head: Int, tail: List = Nil) extends List {
def isEmpty: Boolean = false
}
List: analysis
5
35 7A =
B = Cons(9, A) = 9
C = Cons(1, Cons(8, B)) = 1 8
structural sharing
/**
* Time - O(1)
* Space - O(1)
*/
def prepend(x: Int): List = Cons(x, this)
/**
* Time - O(n)
* Space - O(n)
*/
def append(x: Int): List =
if (isEmpty) Cons(x)
else Cons(head, tail.append(x))
List: append & prepend
6
35 79
35 7 9
List: apply
7
35 7 42 6
n - 1
/**
* Time - O(n)
* Space - O(n)
*/
def apply(n: Int): A =
if (isEmpty) fail("Index out of bounds.")
else if (n == 0) head
else tail(n - 1) // or tail.apply(n - 1)
List: concat
8
path copying
A = 42 6
B = 35 7
C = A.concat(B) = 42 6
/**
* Time - O(n)
* Space - O(n)
*/
def concat(xs: List): List =
if (isEmpty) xs
else tail.concat(xs).prepend(head)
List: reverse (two approaches)
9
42 6 46 2reverse( ) =
def reverse: List =
if (isEmpty) Nil
else tail.reverse.append(head)
, or tail recursion in O(n)
The straightforward solution in O(n2)
def reverse: List = {
@tailrec
def loop(s: List, d: List): List =
if (s.isEmpty) d
else loop(s.tail, d.prepend(s.head))
loop(this, Nil)
}
List performance
10
prepend
head
tail
append
apply
reverse
concat
Banker’s Queue
• Based on two lists (in and out)
• Guarantees amortized O(1) performance
11
class Queue(in: List[Int] = Nil, out: List[Int] = Nil) {
def enqueue(x: Int): Queue = ???
def dequeue: (Int, Queue) = ???
def front: Int = dequeue match { case (a, _) => a }
def rear: Queue = dequeue match { case (_, q) => q }
def isEmpty: Boolean = in.isEmpty && out.isEmpty
}
Queue: analysis
12
A = new Queue( , )
B = A.enqueue(1) = 1 , )
C = B.enqueue(2) = 12 , )
D = C.enqueue(3) = 23 1 , )
(V, E) = D.dequeue = , ))2 3
(U, F) = E.dequeue = , ))3
reverse
new Queue(
new Queue(
new Queue(
(1, new Queue(
(2, new Queue(
Amortized vs. Average Case
• Average Case analysis makes assumptions about
typical (most likely) input
• Amortized analysis considers total performance of
sequence of operations in a the worst case
Example:
• Dynamically-Resizing Array (java.util.ArrayList)
– Has O(n) average case performance for add operation
– It can be amortized to O(1)
• Usually it takes O(1) since the storage is big enough
• Sometimes it can take O(n) due to reallocation & copying
13
Queue: enqueue & dequeue
14
/**
* Time - O(1)
* Space - O(1)
*/
def enqueue(x: Int): Queue = new Queue(x :: in, out)
/**
* Time - O(1)
* Space - O(1)
*/
def dequeue: (Int, Queue) = out match {
case hd :: tl => (hd, new Queue(in, tl)) // O(1)
case Nil => in.reverse match { // O(n)
case hd :: tl => (hd, new Queue(Nil, tl))
case Nil => fail("Empty queue.")
}
}
Queue performance
15
enqueue
dequeue*
front*
rear*
* amortized complexity
Binary Search Tree
16
5
2 7
1 3 8
BST hierarchy
17
abstract sealed class Tree {
def value: Int
def left: Tree
def right: Tree
def isEmpty: Boolean
}
case object Leaf extends Tree {
def value: Int = fail("Empty tree.")
def left: Tree = fail("Empty tree.")
def right: Tree = fail("Empty tree.")
def isEmpty: Boolean = true
}
case class Branch(value: Int,
left: Tree = Leaf,
right: Tree = Leaf) extends Tree {
def isEmpty: Boolean = false
}
5
Branch
Leaf
BST: analysis
18
A = Branch(5) = 5
B = Branch(7, A, Branch(9)) = 7
9
C = Branch(1, Leaf, B) = 1
structural sharing
BST: insert
19
5
2 7
1 3 86
path copying
7
5
/**
* Time - O(log n)
* Space - O(log n)
*/
def add(x: Int): Tree =
if (isEmpty) Branch(x)
else if (x < value) Branch(value, left.add(x), right)
else if (x > value) Branch(value, left, right.add(x))
else this
BST: remove (cases)
20
5
2 7
1 3 8
5
2 7
1 3 8
5
2 7
1 3 8
BST: remove (code)
21
/**
* Time - O(log n)
* Space - O(log n)
*/
def remove(x: Int): Tree =
if (isEmpty) fail("Can't find " + x + " in this tree.")
else if (x < value) Branch(value, left.remove(x), right)
else if (x > value) Branch(value, left, right.remove(x))
else {
if (left.isEmpty && right.isEmpty) Leaf // case 1
else if (left.isEmpty) right // case 2
else if (right.isEmpty) left // case 2
else { // case 3
val succ = right.min // case 3
Branch(succ, left, right.remove(succ)) // case 3
}
}
/**
* Time - O(log n)
* Space - O(log n)
*/
def min: Int = {
@tailrec def loop(t: Tree, m: Int): Int =
if (t.isEmpty) m else loop(t.left, t.value)
if (isEmpty) fail("Empty tree.")
else loop(left, value)
}
/**
* Time - O(log n)
* Space - O(log n)
*/
def max: Int = {
@tailrec def loop(t: Tree[Int], m: Int): Int =
if (t.isEmpty) m else loop(t.right, t.value)
if (isEmpty) fail("Empty tree.")
else loop(right, value)
}
BST: min & max
22
5
2 7
1 3 8
5
2 7
1 3 8
BST: apply
23
5
2 7
1 3 6 8
n - 1
/**
* Time - O(log n)
* Space - O(log n)
*/
def apply(n: Int): A =
if (isEmpty) fail("Tree doesn't contain a " + n + "th element.")
else if (n < left.size) left(n)
else if (n > left.size) right(n - size - 1)
else value
BST: DFS (pre-order traversal)
24
/**
* Time - O(n)
* Space - O(log n)
*/
def valuesByDepth: List[Int] = {
def loop(s: List[Tree]): List[Int] =
if (s.isEmpty) Nil
else if (s.head.isEmpty) loop(s.tail)
else s.head.value :: loop(s.head.right :: s.head.left :: s.tail)
loop(List(this))
}
5
2 7
1 3 8
BST: BFS (level-order traversal)
25
/**
* Time - O(n)
* Space - O(log n)
*/
def valuesByBreadth: List[Int] = {
import scala.collection.immutable.Queue
def loop(q: Queue[Tree]): List[Int] =
if (q.isEmpty) Nil
else if (q.head.isEmpty) loop(q.tail)
else q.head.value :: loop(q.tail :+ q.head.left :+ q.head.right)
loop(Queue(this))
}
5
2 7
1 3 8
BST: inverse (problem)
26
-5
-7 -2
-8 -3 -1
5
2 7
1 3 8
invert
BST: inverse (solution)
27
/**
* Time - O(n)
* Space - O(log n)
*/
def invert: Tree =
if (isEmpty) Leaf else Branch(-value, right.invert, left.invert)
BST performance
28
insert
contains
remove
min
max
apply
bfs
dfs
How fast BST?
29
It’s extremely fast if it’s balanced
Balanced BST: Red-Black Tree
• Red invariant: No red node has red parent
• Black invariant: Every root-to-leaf path contains
the same number of black nodes
• Suggested by Chris Okasaki in his paper “Red-Black
Trees in a Functional Settings”
• Asymptotically optimal implementation
• Easy to understand and implement
30
R-B Tree chart sheet
31
z
y
x
x
y
z
z
y
x
z
x
y
x
z
y
Double Rotation
Double Rotation
Single Rotation
Single Rotation
R-B Tree: balanced insert
32
def balancedAdd(x: Int): Tree =
if (isEmpty) RedBranch(x)
else if (x < value) balance(isBlack, value, left.balancedAdd(x), right)
else if (x > value) balance(isBlack, value, left, right.balancedAdd(x))
else this
def balance(b: Boolean, x: Int, left: Tree, right: Tree): Tree =
(b, left, right) match {
case (true, RedBranch(y, RedBranch(z, a, b), c), d) =>
BlackBranch(y, RedBranch(z, a, b), RedBranch(x, c, d))
case (true, a, RedBranch(y, b, RedBranch(z, c, d))) =>
BlackBranch(y, RedBranch(x, a, b), RedBranch(z, c, d))
case (true, RedBranch(z, a, RedBranch(y, b, c)), d) =>
BlackBranch(y, RedBranch(z, a, b), RedBranch(x, c, d))
case (true, a, RedBranch(z, RedBranch(y, b, c), d)) =>
BlackBranch(y, RedBranch(x, a, b), RedBranch(z, c, d))
case (true, _, _) => BlackBranch(x, left, right)
case (false, _, _) => RedBranch(x, left, right)
}
What about Scala?
• Scala has Singly-Linked List
– scala.collection.immutable.List
• Scala has Banker’s Queue
– scala.collection.immutable.Queue
• Scala has Balanced BST (R-B Tree)
– scala.collection.immutable.TreeSet
– scala.collection.immutable.TreeMap
• And a bit more …
33
Patricia Trie
34
Binary Trie analysis
35
{ 1 -> “one”, 4 -> “four”, 5 -> “five” }
0 1
00 10 1101
100
four
001 101
one five
Patricia Trie analysis
36
{ 1 -> “one”, 4 -> “four”, 5 -> “five” }
1
44 -> four
1 -> one 5 -> five
Branching Bit
= 0x001
= 0x100
Hash Array Mapped Trie
37
HMAT analysis
38
● ... ●
● ... ● ● ... ●
1 2 ... 32 993 994 ... 1024 31755 31756 ... 31786 32737 32736 ... 32768
Bedtime Reading
• Okasaki’s Purely Functional Data Structures
• http://okasaki.blogspot.com/
• https://github.com/vkostyukov/scalacaster
• http://www.codecommit.com/blog/
• http://cstheory.stackexchange.com/questions/1539/whats-new-in-
purely-functional-data-structures-since-okasaki
39
40
vkostyukov
vkostyukov

More Related Content

What's hot

Algebraic Data Types for Data Oriented Programming - From Haskell and Scala t...
Algebraic Data Types forData Oriented Programming - From Haskell and Scala t...Algebraic Data Types forData Oriented Programming - From Haskell and Scala t...
Algebraic Data Types for Data Oriented Programming - From Haskell and Scala t...Philip Schwarz
 
Data Structures In Scala
Data Structures In ScalaData Structures In Scala
Data Structures In ScalaKnoldus Inc.
 
Blazing Fast, Pure Effects without Monads — LambdaConf 2018
Blazing Fast, Pure Effects without Monads — LambdaConf 2018Blazing Fast, Pure Effects without Monads — LambdaConf 2018
Blazing Fast, Pure Effects without Monads — LambdaConf 2018John De Goes
 
Functional Programming 101 with Scala and ZIO @FunctionalWorld
Functional Programming 101 with Scala and ZIO @FunctionalWorldFunctional Programming 101 with Scala and ZIO @FunctionalWorld
Functional Programming 101 with Scala and ZIO @FunctionalWorldJorge Vásquez
 
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 1
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 1Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 1
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 1Philip Schwarz
 
Reitit - Clojure/North 2019
Reitit - Clojure/North 2019Reitit - Clojure/North 2019
Reitit - Clojure/North 2019Metosin Oy
 
Reactive Microservice Architecture with Groovy and Grails
Reactive Microservice Architecture with Groovy and GrailsReactive Microservice Architecture with Groovy and Grails
Reactive Microservice Architecture with Groovy and GrailsSteve Pember
 
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 2
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 2Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 2
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 2Philip Schwarz
 
Capabilities for Resources and Effects
Capabilities for Resources and EffectsCapabilities for Resources and Effects
Capabilities for Resources and EffectsMartin Odersky
 
Functor, Apply, Applicative And Monad
Functor, Apply, Applicative And MonadFunctor, Apply, Applicative And Monad
Functor, Apply, Applicative And MonadOliver Daff
 
Monoids - Part 1 - with examples using Scalaz and Cats
Monoids - Part 1 - with examples using Scalaz and CatsMonoids - Part 1 - with examples using Scalaz and Cats
Monoids - Part 1 - with examples using Scalaz and CatsPhilip Schwarz
 
The Power of Composition (NDC Oslo 2020)
The Power of Composition (NDC Oslo 2020)The Power of Composition (NDC Oslo 2020)
The Power of Composition (NDC Oslo 2020)Scott Wlaschin
 
Hot C++: Rvalue References And Move Semantics
Hot C++: Rvalue References And Move SemanticsHot C++: Rvalue References And Move Semantics
Hot C++: Rvalue References And Move SemanticsAndrey Upadyshev
 
Functors, Applicatives and Monads In Scala
Functors, Applicatives and Monads In ScalaFunctors, Applicatives and Monads In Scala
Functors, Applicatives and Monads In ScalaKnoldus Inc.
 
Java 8 lambda expressions
Java 8 lambda expressionsJava 8 lambda expressions
Java 8 lambda expressionsLogan Chien
 

What's hot (20)

Algebraic Data Types for Data Oriented Programming - From Haskell and Scala t...
Algebraic Data Types forData Oriented Programming - From Haskell and Scala t...Algebraic Data Types forData Oriented Programming - From Haskell and Scala t...
Algebraic Data Types for Data Oriented Programming - From Haskell and Scala t...
 
Data Structures In Scala
Data Structures In ScalaData Structures In Scala
Data Structures In Scala
 
Blazing Fast, Pure Effects without Monads — LambdaConf 2018
Blazing Fast, Pure Effects without Monads — LambdaConf 2018Blazing Fast, Pure Effects without Monads — LambdaConf 2018
Blazing Fast, Pure Effects without Monads — LambdaConf 2018
 
Functional Programming 101 with Scala and ZIO @FunctionalWorld
Functional Programming 101 with Scala and ZIO @FunctionalWorldFunctional Programming 101 with Scala and ZIO @FunctionalWorld
Functional Programming 101 with Scala and ZIO @FunctionalWorld
 
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 1
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 1Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 1
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 1
 
Reitit - Clojure/North 2019
Reitit - Clojure/North 2019Reitit - Clojure/North 2019
Reitit - Clojure/North 2019
 
Applicative style programming
Applicative style programmingApplicative style programming
Applicative style programming
 
ZIO Queue
ZIO QueueZIO Queue
ZIO Queue
 
Preparing for Scala 3
Preparing for Scala 3Preparing for Scala 3
Preparing for Scala 3
 
Reactive Microservice Architecture with Groovy and Grails
Reactive Microservice Architecture with Groovy and GrailsReactive Microservice Architecture with Groovy and Grails
Reactive Microservice Architecture with Groovy and Grails
 
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 2
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 2Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 2
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 2
 
Java 8 Lambda and Streams
Java 8 Lambda and StreamsJava 8 Lambda and Streams
Java 8 Lambda and Streams
 
Capabilities for Resources and Effects
Capabilities for Resources and EffectsCapabilities for Resources and Effects
Capabilities for Resources and Effects
 
Functor, Apply, Applicative And Monad
Functor, Apply, Applicative And MonadFunctor, Apply, Applicative And Monad
Functor, Apply, Applicative And Monad
 
Monoids - Part 1 - with examples using Scalaz and Cats
Monoids - Part 1 - with examples using Scalaz and CatsMonoids - Part 1 - with examples using Scalaz and Cats
Monoids - Part 1 - with examples using Scalaz and Cats
 
The Power of Composition (NDC Oslo 2020)
The Power of Composition (NDC Oslo 2020)The Power of Composition (NDC Oslo 2020)
The Power of Composition (NDC Oslo 2020)
 
Hot C++: Rvalue References And Move Semantics
Hot C++: Rvalue References And Move SemanticsHot C++: Rvalue References And Move Semantics
Hot C++: Rvalue References And Move Semantics
 
Functors, Applicatives and Monads In Scala
Functors, Applicatives and Monads In ScalaFunctors, Applicatives and Monads In Scala
Functors, Applicatives and Monads In Scala
 
Sets in python
Sets in pythonSets in python
Sets in python
 
Java 8 lambda expressions
Java 8 lambda expressionsJava 8 lambda expressions
Java 8 lambda expressions
 

Similar to Purely Functional Data Structures in Scala

JDD2015: Functional programing and Event Sourcing - a pair made in heaven - e...
JDD2015: Functional programing and Event Sourcing - a pair made in heaven - e...JDD2015: Functional programing and Event Sourcing - a pair made in heaven - e...
JDD2015: Functional programing and Event Sourcing - a pair made in heaven - e...PROIDEA
 
CS-102 BST_27_3_14v2.pdf
CS-102 BST_27_3_14v2.pdfCS-102 BST_27_3_14v2.pdf
CS-102 BST_27_3_14v2.pdfssuser034ce1
 
Lispprograaming excercise
Lispprograaming excerciseLispprograaming excercise
Lispprograaming excerciseilias ahmed
 
Data structures in scala
Data structures in scalaData structures in scala
Data structures in scalaMeetu Maltiar
 
High Wizardry in the Land of Scala
High Wizardry in the Land of ScalaHigh Wizardry in the Land of Scala
High Wizardry in the Land of Scaladjspiewak
 
Python3 cheatsheet
Python3 cheatsheetPython3 cheatsheet
Python3 cheatsheetGil Cohen
 
lecture 12
lecture 12lecture 12
lecture 12sajinsc
 
Review session2
Review session2Review session2
Review session2NEEDY12345
 
Mementopython3 english
Mementopython3 englishMementopython3 english
Mementopython3 englishssuser442080
 
Mementopython3 english
Mementopython3 englishMementopython3 english
Mementopython3 englishyassminkhaldi1
 
Advance LISP (Artificial Intelligence)
Advance LISP (Artificial Intelligence) Advance LISP (Artificial Intelligence)
Advance LISP (Artificial Intelligence) wahab khan
 
Introduction to python cheat sheet for all
Introduction to python cheat sheet for allIntroduction to python cheat sheet for all
Introduction to python cheat sheet for allshwetakushwaha45
 
Functional programming with_scala
Functional programming with_scalaFunctional programming with_scala
Functional programming with_scalaRaymond Tay
 
lecture 13
lecture 13lecture 13
lecture 13sajinsc
 
R Cheat Sheet for Data Analysts and Statisticians.pdf
R Cheat Sheet for Data Analysts and Statisticians.pdfR Cheat Sheet for Data Analysts and Statisticians.pdf
R Cheat Sheet for Data Analysts and Statisticians.pdfTimothy McBush Hiele
 

Similar to Purely Functional Data Structures in Scala (20)

JDD2015: Functional programing and Event Sourcing - a pair made in heaven - e...
JDD2015: Functional programing and Event Sourcing - a pair made in heaven - e...JDD2015: Functional programing and Event Sourcing - a pair made in heaven - e...
JDD2015: Functional programing and Event Sourcing - a pair made in heaven - e...
 
CS-102 BST_27_3_14v2.pdf
CS-102 BST_27_3_14v2.pdfCS-102 BST_27_3_14v2.pdf
CS-102 BST_27_3_14v2.pdf
 
Zippers
ZippersZippers
Zippers
 
Lispprograaming excercise
Lispprograaming excerciseLispprograaming excercise
Lispprograaming excercise
 
Functional programming in scala
Functional programming in scalaFunctional programming in scala
Functional programming in scala
 
Data structures in scala
Data structures in scalaData structures in scala
Data structures in scala
 
High Wizardry in the Land of Scala
High Wizardry in the Land of ScalaHigh Wizardry in the Land of Scala
High Wizardry in the Land of Scala
 
Python_ 3 CheatSheet
Python_ 3 CheatSheetPython_ 3 CheatSheet
Python_ 3 CheatSheet
 
Python3 cheatsheet
Python3 cheatsheetPython3 cheatsheet
Python3 cheatsheet
 
lecture 12
lecture 12lecture 12
lecture 12
 
Review session2
Review session2Review session2
Review session2
 
Mementopython3 english
Mementopython3 englishMementopython3 english
Mementopython3 english
 
Python3
Python3Python3
Python3
 
Mementopython3 english
Mementopython3 englishMementopython3 english
Mementopython3 english
 
Advance LISP (Artificial Intelligence)
Advance LISP (Artificial Intelligence) Advance LISP (Artificial Intelligence)
Advance LISP (Artificial Intelligence)
 
Introduction to python cheat sheet for all
Introduction to python cheat sheet for allIntroduction to python cheat sheet for all
Introduction to python cheat sheet for all
 
Functional programming with_scala
Functional programming with_scalaFunctional programming with_scala
Functional programming with_scala
 
lecture 13
lecture 13lecture 13
lecture 13
 
R Cheat Sheet for Data Analysts and Statisticians.pdf
R Cheat Sheet for Data Analysts and Statisticians.pdfR Cheat Sheet for Data Analysts and Statisticians.pdf
R Cheat Sheet for Data Analysts and Statisticians.pdf
 
2 depth first
2 depth first2 depth first
2 depth first
 

Recently uploaded

Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Scott Keck-Warren
 
APIForce Zurich 5 April Automation LPDG
APIForce Zurich 5 April  Automation LPDGAPIForce Zurich 5 April  Automation LPDG
APIForce Zurich 5 April Automation LPDGMarianaLemus7
 
costume and set research powerpoint presentation
costume and set research powerpoint presentationcostume and set research powerpoint presentation
costume and set research powerpoint presentationphoebematthew05
 
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationBeyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationSafe Software
 
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks..."LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...Fwdays
 
CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):comworks
 
Understanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitectureUnderstanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitecturePixlogix Infotech
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLScyllaDB
 
Pigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions
 
Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 3652toLead Limited
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxNavinnSomaal
 
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr LapshynFwdays
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Mattias Andersson
 
Artificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxArtificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxhariprasad279825
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Patryk Bandurski
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Commit University
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsRizwan Syed
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubKalema Edgar
 

Recently uploaded (20)

E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptxE-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
 
Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024
 
APIForce Zurich 5 April Automation LPDG
APIForce Zurich 5 April  Automation LPDGAPIForce Zurich 5 April  Automation LPDG
APIForce Zurich 5 April Automation LPDG
 
costume and set research powerpoint presentation
costume and set research powerpoint presentationcostume and set research powerpoint presentation
costume and set research powerpoint presentation
 
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationBeyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
 
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks..."LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
 
CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):
 
Understanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitectureUnderstanding the Laravel MVC Architecture
Understanding the Laravel MVC Architecture
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQL
 
Pigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food Manufacturing
 
Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptx
 
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?
 
Artificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxArtificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptx
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL Certs
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding Club
 
Hot Sexy call girls in Panjabi Bagh 🔝 9953056974 🔝 Delhi escort Service
Hot Sexy call girls in Panjabi Bagh 🔝 9953056974 🔝 Delhi escort ServiceHot Sexy call girls in Panjabi Bagh 🔝 9953056974 🔝 Delhi escort Service
Hot Sexy call girls in Panjabi Bagh 🔝 9953056974 🔝 Delhi escort Service
 

Purely Functional Data Structures in Scala

  • 1. Purely Functional Data Structures in Scala Vladimir Kostyukov http://vkostyukov.ru
  • 2. Agenda • Immutability & Persistence • Singly-Linked List • Banker’s Queue • Binary Search Tree • Balanced BST: Red-Black Tree • Scala support of these things • Patricia Trie • Hash Array Mapped Trie 2
  • 3. Immutability & Persistence Two problems: • FP paradigm doesn’t support destructive updates • FP paradigm expects both the old and new versions of DS will be available after update Two solutions: • Immutable objects aren’t changeable • Persistent objects support multiple versions 3
  • 4. Singly-Linked List 4 35 7 Cons Nil abstract sealed class List { def head: Int def tail: List def isEmpty: Boolean } case object Nil extends List { def head: Int = fail("Empty list.") def tail: List = fail("Empty list.") def isEmpty: Boolean = true } case class Cons(head: Int, tail: List = Nil) extends List { def isEmpty: Boolean = false }
  • 5. List: analysis 5 35 7A = B = Cons(9, A) = 9 C = Cons(1, Cons(8, B)) = 1 8 structural sharing
  • 6. /** * Time - O(1) * Space - O(1) */ def prepend(x: Int): List = Cons(x, this) /** * Time - O(n) * Space - O(n) */ def append(x: Int): List = if (isEmpty) Cons(x) else Cons(head, tail.append(x)) List: append & prepend 6 35 79 35 7 9
  • 7. List: apply 7 35 7 42 6 n - 1 /** * Time - O(n) * Space - O(n) */ def apply(n: Int): A = if (isEmpty) fail("Index out of bounds.") else if (n == 0) head else tail(n - 1) // or tail.apply(n - 1)
  • 8. List: concat 8 path copying A = 42 6 B = 35 7 C = A.concat(B) = 42 6 /** * Time - O(n) * Space - O(n) */ def concat(xs: List): List = if (isEmpty) xs else tail.concat(xs).prepend(head)
  • 9. List: reverse (two approaches) 9 42 6 46 2reverse( ) = def reverse: List = if (isEmpty) Nil else tail.reverse.append(head) , or tail recursion in O(n) The straightforward solution in O(n2) def reverse: List = { @tailrec def loop(s: List, d: List): List = if (s.isEmpty) d else loop(s.tail, d.prepend(s.head)) loop(this, Nil) }
  • 11. Banker’s Queue • Based on two lists (in and out) • Guarantees amortized O(1) performance 11 class Queue(in: List[Int] = Nil, out: List[Int] = Nil) { def enqueue(x: Int): Queue = ??? def dequeue: (Int, Queue) = ??? def front: Int = dequeue match { case (a, _) => a } def rear: Queue = dequeue match { case (_, q) => q } def isEmpty: Boolean = in.isEmpty && out.isEmpty }
  • 12. Queue: analysis 12 A = new Queue( , ) B = A.enqueue(1) = 1 , ) C = B.enqueue(2) = 12 , ) D = C.enqueue(3) = 23 1 , ) (V, E) = D.dequeue = , ))2 3 (U, F) = E.dequeue = , ))3 reverse new Queue( new Queue( new Queue( (1, new Queue( (2, new Queue(
  • 13. Amortized vs. Average Case • Average Case analysis makes assumptions about typical (most likely) input • Amortized analysis considers total performance of sequence of operations in a the worst case Example: • Dynamically-Resizing Array (java.util.ArrayList) – Has O(n) average case performance for add operation – It can be amortized to O(1) • Usually it takes O(1) since the storage is big enough • Sometimes it can take O(n) due to reallocation & copying 13
  • 14. Queue: enqueue & dequeue 14 /** * Time - O(1) * Space - O(1) */ def enqueue(x: Int): Queue = new Queue(x :: in, out) /** * Time - O(1) * Space - O(1) */ def dequeue: (Int, Queue) = out match { case hd :: tl => (hd, new Queue(in, tl)) // O(1) case Nil => in.reverse match { // O(n) case hd :: tl => (hd, new Queue(Nil, tl)) case Nil => fail("Empty queue.") } }
  • 17. BST hierarchy 17 abstract sealed class Tree { def value: Int def left: Tree def right: Tree def isEmpty: Boolean } case object Leaf extends Tree { def value: Int = fail("Empty tree.") def left: Tree = fail("Empty tree.") def right: Tree = fail("Empty tree.") def isEmpty: Boolean = true } case class Branch(value: Int, left: Tree = Leaf, right: Tree = Leaf) extends Tree { def isEmpty: Boolean = false } 5 Branch Leaf
  • 18. BST: analysis 18 A = Branch(5) = 5 B = Branch(7, A, Branch(9)) = 7 9 C = Branch(1, Leaf, B) = 1 structural sharing
  • 19. BST: insert 19 5 2 7 1 3 86 path copying 7 5 /** * Time - O(log n) * Space - O(log n) */ def add(x: Int): Tree = if (isEmpty) Branch(x) else if (x < value) Branch(value, left.add(x), right) else if (x > value) Branch(value, left, right.add(x)) else this
  • 20. BST: remove (cases) 20 5 2 7 1 3 8 5 2 7 1 3 8 5 2 7 1 3 8
  • 21. BST: remove (code) 21 /** * Time - O(log n) * Space - O(log n) */ def remove(x: Int): Tree = if (isEmpty) fail("Can't find " + x + " in this tree.") else if (x < value) Branch(value, left.remove(x), right) else if (x > value) Branch(value, left, right.remove(x)) else { if (left.isEmpty && right.isEmpty) Leaf // case 1 else if (left.isEmpty) right // case 2 else if (right.isEmpty) left // case 2 else { // case 3 val succ = right.min // case 3 Branch(succ, left, right.remove(succ)) // case 3 } }
  • 22. /** * Time - O(log n) * Space - O(log n) */ def min: Int = { @tailrec def loop(t: Tree, m: Int): Int = if (t.isEmpty) m else loop(t.left, t.value) if (isEmpty) fail("Empty tree.") else loop(left, value) } /** * Time - O(log n) * Space - O(log n) */ def max: Int = { @tailrec def loop(t: Tree[Int], m: Int): Int = if (t.isEmpty) m else loop(t.right, t.value) if (isEmpty) fail("Empty tree.") else loop(right, value) } BST: min & max 22 5 2 7 1 3 8 5 2 7 1 3 8
  • 23. BST: apply 23 5 2 7 1 3 6 8 n - 1 /** * Time - O(log n) * Space - O(log n) */ def apply(n: Int): A = if (isEmpty) fail("Tree doesn't contain a " + n + "th element.") else if (n < left.size) left(n) else if (n > left.size) right(n - size - 1) else value
  • 24. BST: DFS (pre-order traversal) 24 /** * Time - O(n) * Space - O(log n) */ def valuesByDepth: List[Int] = { def loop(s: List[Tree]): List[Int] = if (s.isEmpty) Nil else if (s.head.isEmpty) loop(s.tail) else s.head.value :: loop(s.head.right :: s.head.left :: s.tail) loop(List(this)) } 5 2 7 1 3 8
  • 25. BST: BFS (level-order traversal) 25 /** * Time - O(n) * Space - O(log n) */ def valuesByBreadth: List[Int] = { import scala.collection.immutable.Queue def loop(q: Queue[Tree]): List[Int] = if (q.isEmpty) Nil else if (q.head.isEmpty) loop(q.tail) else q.head.value :: loop(q.tail :+ q.head.left :+ q.head.right) loop(Queue(this)) } 5 2 7 1 3 8
  • 26. BST: inverse (problem) 26 -5 -7 -2 -8 -3 -1 5 2 7 1 3 8 invert
  • 27. BST: inverse (solution) 27 /** * Time - O(n) * Space - O(log n) */ def invert: Tree = if (isEmpty) Leaf else Branch(-value, right.invert, left.invert)
  • 29. How fast BST? 29 It’s extremely fast if it’s balanced
  • 30. Balanced BST: Red-Black Tree • Red invariant: No red node has red parent • Black invariant: Every root-to-leaf path contains the same number of black nodes • Suggested by Chris Okasaki in his paper “Red-Black Trees in a Functional Settings” • Asymptotically optimal implementation • Easy to understand and implement 30
  • 31. R-B Tree chart sheet 31 z y x x y z z y x z x y x z y Double Rotation Double Rotation Single Rotation Single Rotation
  • 32. R-B Tree: balanced insert 32 def balancedAdd(x: Int): Tree = if (isEmpty) RedBranch(x) else if (x < value) balance(isBlack, value, left.balancedAdd(x), right) else if (x > value) balance(isBlack, value, left, right.balancedAdd(x)) else this def balance(b: Boolean, x: Int, left: Tree, right: Tree): Tree = (b, left, right) match { case (true, RedBranch(y, RedBranch(z, a, b), c), d) => BlackBranch(y, RedBranch(z, a, b), RedBranch(x, c, d)) case (true, a, RedBranch(y, b, RedBranch(z, c, d))) => BlackBranch(y, RedBranch(x, a, b), RedBranch(z, c, d)) case (true, RedBranch(z, a, RedBranch(y, b, c)), d) => BlackBranch(y, RedBranch(z, a, b), RedBranch(x, c, d)) case (true, a, RedBranch(z, RedBranch(y, b, c), d)) => BlackBranch(y, RedBranch(x, a, b), RedBranch(z, c, d)) case (true, _, _) => BlackBranch(x, left, right) case (false, _, _) => RedBranch(x, left, right) }
  • 33. What about Scala? • Scala has Singly-Linked List – scala.collection.immutable.List • Scala has Banker’s Queue – scala.collection.immutable.Queue • Scala has Balanced BST (R-B Tree) – scala.collection.immutable.TreeSet – scala.collection.immutable.TreeMap • And a bit more … 33
  • 35. Binary Trie analysis 35 { 1 -> “one”, 4 -> “four”, 5 -> “five” } 0 1 00 10 1101 100 four 001 101 one five
  • 36. Patricia Trie analysis 36 { 1 -> “one”, 4 -> “four”, 5 -> “five” } 1 44 -> four 1 -> one 5 -> five Branching Bit = 0x001 = 0x100
  • 37. Hash Array Mapped Trie 37
  • 38. HMAT analysis 38 ● ... ● ● ... ● ● ... ● 1 2 ... 32 993 994 ... 1024 31755 31756 ... 31786 32737 32736 ... 32768
  • 39. Bedtime Reading • Okasaki’s Purely Functional Data Structures • http://okasaki.blogspot.com/ • https://github.com/vkostyukov/scalacaster • http://www.codecommit.com/blog/ • http://cstheory.stackexchange.com/questions/1539/whats-new-in- purely-functional-data-structures-since-okasaki 39