Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Immutable data structures for functional JavaScript

Immutable data structures for functional JavaScript

Presented at O'Reilly Fluent 2017: https://conferences.oreilly.com/fluent/fl-ca/public/schedule/detail/58872

Functional programming has been gaining popularity in the JavaScript community, and for good reason: rejecting side-effects and mutability (in-place changes to data) helps avoid a lot of headaches.

But even if you refuse to mutate objects, you’ll still need to deal with transformations to data. In a purely immutable world, this means you have to create a whole new object each time something changes, which can slow things down and eat up memory, making functional programming seem inefficient.

That’s where immutable data structures come in to save the day—and time and space. Also called persistent data structures, they help you efficiently make new “modified” versions of immutable objects by reusing parts of the old object that you don’t need to change. By making immutability efficient, such data structures are fantastic for functional programming and play a central role in functional languages such as Clojure.

Anjana Vakil explains how the concept of structural sharing makes efficient immutable data structures possible and demonstrates how they work under the hood. Anjana also offers an overview of two libraries—Mori and Immutable.js—that let you easily take advantage of these remarkable data structures in your JavaScript code. You’ll leave armed with a deeper understanding of how immutable data structures work and the practical knowledge to leverage them in your own functional JavaScript projects.

Anjana Sofia Vakil

June 21, 2017
Tweet

More Decks by Anjana Sofia Vakil

Other Decks in Programming

Transcript

  1. @AnjanaVakil O’Reilly Fluent 2017

    View Slide

  2. hi!
    i’m anjana
    The
    Recurse
    Center

    View Slide

  3. functional
    programming
    rocks!

    View Slide

  4. functional
    programming
    pure functions
    ● input → output
    ● side effects
    ● data in, data out
    mutable state

    View Slide

  5. Immutability
    rocks!

    View Slide

  6. rocks rock!

    View Slide

  7. Nobody sits like this rock sits.
    You rock, rock.
    The rock just sits, and is.
    You show us how to just sit
    here, and that's what we need.
    - I ❤ Huckabees (2004)
    rocks rock!

    View Slide

  8. in A land where
    mutation reigns...

    View Slide

  9. 0 1 2 3 4 5 6 7
    foo

    View Slide

  10. zoo
    1
    0 3
    2 5
    4 7
    6

    View Slide

  11. zoo
    1
    0 3
    2 5
    4 7
    6

    View Slide

  12. zoo
    1
    0 3
    2 5
    4 7
    6
    Who put a
    in my zoo?!?

    View Slide

  13. with mutability
    come overhead
    & bugs

    View Slide

  14. Mutation must
    be stopped!
    (sorry, xavier)

    View Slide

  15. Mutation must
    be stopped!
    (sorry, xavier)
    let’s journey to
    the land of...

    View Slide

  16. immutable
    data!
    it just sits, and is
    (like rocks)

    View Slide

  17. zoo
    1
    0 3
    2 5
    4 7
    6

    View Slide

  18. new
    zoo
    1
    0 3
    2 5
    4 7
    6

    View Slide

  19. new
    zoo
    1
    0 3
    2 5
    4 7
    6

    View Slide

  20. new
    zoo
    1
    0 3
    2 5
    4 7
    6

    View Slide

  21. new
    zoo
    1
    0 3
    2 5
    4 7
    6
    Great!
    My zoo just
    sits, and is!

    View Slide

  22. new
    zoo
    1
    0 3
    2 5
    4 7
    6
    ...but my
    code runs
    like
    &

    View Slide

  23. copying wastes
    time & space

    View Slide

  24. isn’t there a
    better way?

    View Slide

  25. isn’t there a
    better way?
    we need
    a hero...

    View Slide

  26. persistent
    data
    structures!

    View Slide

  27. persistent
    data
    structures!
    masters of
    time & space!

    View Slide

  28. persistent
    data
    structures!
    old versions
    stay put...
    masters of
    time & space!

    View Slide

  29. persistent
    data
    structures!
    old versions
    stay put...
    ... new versions
    created efficiently!
    masters of
    time & space!

    View Slide

  30. What’s the source
    of their power?

    View Slide

  31. Trees!

    View Slide

  32. zoo
    1
    0 3
    2 5
    4 7
    6

    View Slide

  33. 1
    0 3
    2 5
    4 7
    6

    View Slide

  34. 1
    0 3
    2 5
    4 7
    6

    View Slide

  35. 1
    0 3
    2 5
    4 7
    6

    View Slide

  36. 1
    0 3
    2 5
    4 7
    6
    zoo

    View Slide

  37. how do we
    update things?

    View Slide

  38. 1
    0 3
    2 5
    4 7
    6
    zoo

    View Slide

  39. 1
    0 3
    2 5
    4 7
    6
    zoo
    1
    0

    View Slide

  40. 1
    0 3
    2 5
    4 7
    6
    zoo
    1
    0

    View Slide

  41. 1
    0 3
    2 5
    4 7
    6
    zoo
    1
    0

    View Slide

  42. 1
    0 3
    2 5
    4 7
    6
    zoo
    1
    0
    new

    View Slide

  43. 1
    0 3
    2 5
    4 7
    6
    zoo
    1
    0
    new
    path
    copying!

    View Slide

  44. 1
    0 3
    2 5
    4 7
    6
    zoo
    1
    0
    new
    Structural
    sharing!
    path
    copying!

    View Slide

  45. 1
    0 3
    2 5
    4 7
    6
    zoo
    1
    0
    new
    Structural
    sharing!
    path
    copying!
    AWESOME!
    I can reuse
    most of the
    data!

    View Slide

  46. Trees + Sharing
    Turn &
    into &

    View Slide

  47. but how do we
    access things?

    View Slide

  48. but how do we
    access things?
    our reveals a
    secret identity...

    View Slide

  49. it’s a Trie!
    leaves hold values
    paths represent keys

    View Slide

  50. ape
    ant bat bee
    a b
    a e
    n p
    t e e
    t
    an ba be
    ap
    a b

    View Slide

  51. ape
    ant bat bee
    a b
    a e
    n p
    t e e
    t
    an ba be
    ap
    a b

    View Slide

  52. ape
    ant bat bee
    a b
    a e
    n p
    t e e
    t
    an ba be
    ap
    a b

    View Slide

  53. ape
    ant bat bee
    a b
    a e
    n p
    t e e
    t
    an ba be
    ap
    a b

    View Slide

  54. convert index
    to binary
    descend trie bit by bit

    View Slide

  55. 001
    000 011
    010 101
    100 111
    110
    zoo
    0 1
    0 1 0 1
    (1)
    (0) (3)
    (2) (5)
    (4) (7)
    (6)

    View Slide

  56. 001
    000 011
    010 101
    100 111
    110
    zoo
    0 1
    0 1 0 1
    (1)
    (0) (3)
    (2) (5)
    (4) (7)
    (6)
    zoo[5]

    View Slide

  57. 001
    000 011
    010 101
    100 111
    110
    zoo
    0 1
    0 1 0 1
    (1)
    (0) (3)
    (2) (5)
    (4) (7)
    (6)
    zoo[5]
    zoo[0b101]

    View Slide

  58. 001
    000 011
    010 101
    100 111
    110
    zoo
    0 1
    0 1 0 1
    (1)
    (0) (3)
    (2) (5)
    (4) (7)
    (6)
    zoo[5]
    zoo[0b101]
    zoo→1→0→1

    View Slide

  59. 001
    000 011
    010 101
    100 111
    110
    zoo
    0 1
    0 1 0 1
    (1)
    (0) (3)
    (2) (5)
    (4) (7)
    (6)
    zoo[5]
    zoo[0b101]
    zoo→1→0→1

    View Slide

  60. 001
    000 011
    010 101
    100 111
    110
    zoo
    0 1
    0 1 1
    (1)
    (0) (3)
    (2) (5)
    (4) (7)
    (6)
    zoo[5]
    zoo[0b101]
    zoo→1→0→1
    0

    View Slide

  61. 001
    000 011
    010 101
    100 111
    110
    zoo
    0 1
    0 1 1
    (1)
    (0) (3)
    (2) (5)
    (4) (7)
    (6)
    zoo[5]
    zoo[0b101]
    zoo→1→0→1
    0

    View Slide

  62. it’s a
    !

    View Slide

  63. it’s a
    !
    it’s a
    !

    View Slide

  64. it’s a
    !
    it’s a
    !
    it’s...

    View Slide

  65. bitmapped
    vector
    trie!

    View Slide

  66. Let’s talk
    complexity...

    View Slide

  67. immutable array
    lookup: O(1)
    update: O(n)
    lookup: O(log n)
    update: O(log n)
    Bitmapped vector trie
    vs.

    View Slide

  68. zoo[18977]
    zoo[0b100101000100001]
    zoo→1→0→0→1→0→1→0→...

    View Slide

  69. zoo[18977]
    zoo[0b100101000100001]
    zoo→1→0→0→1→0→1→0→...
    this is taking
    forever….

    View Slide

  70. who said the needs
    2-way branching?!?
    ( bit per level)

    View Slide

  71. who said the needs
    2-way branching?!?
    ( bit per level)
    we can choose...

    View Slide

  72. fewer branches
    - deep trees
    + small nodes
    + shallow trees
    - large nodes
    more branches
    vs.

    View Slide

  73. 32-way branching
    is a good balance!
    ( bits per level)

    View Slide

  74. zoo[18977]
    zoo[0b100101000100001]
    zoo→10010→10001→00001

    View Slide

  75. immutable array
    lookup: O(1)
    update: O(n)
    lookup: O(log n)
    update: O(log n)
    Bitmapped vector trie
    vs.

    View Slide

  76. immutable array
    lookup: O(1)
    update: O(n)
    lookup: O(log
    32
    n)
    update: O(log
    32
    n)
    Bitmapped vector trie
    vs.

    View Slide

  77. immutable array
    lookup: O(1)
    update: O(n)
    lookup ≈ O(1)
    update ≈ O(1)
    Bitmapped vector trie
    vs.

    View Slide

  78. What about
    objects?
    We need non-integer
    keys too

    View Slide

  79. zoo
    "k"
    "m" "b"
    "l" "g"
    "f" "w"
    "t"

    View Slide

  80. hash the
    to get a number
    descend trie as before

    View Slide

  81. zoo["g"]
    hash("g") === 5 === 0b101
    zoo→1→0→1

    View Slide

  82. 001
    000 011
    010 101
    100 111
    110
    zoo
    0 1
    0 1 1
    zoo[hash("g")]
    zoo[0b101]
    zoo→1→0→1
    0
    "k"
    "m" "b"
    "l" "g"
    "f" "w"
    "t"

    View Slide

  83. 001
    000 011
    010 101
    100 111
    110
    zoo
    0 1
    0 1 1
    0
    "k"
    "m" "b"
    "l" "g"
    "f" "w"
    "t"
    Awesome!
    I can use
    whatever
    s I want!
    zoo[hash("g")]
    zoo[0b101]
    zoo→1→0→1

    View Slide

  84. hash
    array mapped
    trie!

    View Slide

  85. Let’s recap!
    mutability:
    immutability:
    copying: &
    sharing: &

    View Slide

  86. these are some
    data structures!
    But how do we use them
    in Javascript?

    View Slide

  87. libraries!
    immutable.js!
    Mori!

    View Slide

  88. View Slide

  89. var Imjs = require("immutable");
    var a = Imjs.List.of(1,2);
    // List [1, 2]
    var a2 = a.push(3);
    // List [1, 2, 3]
    a.size; // 2
    a2.get(2); // 3

    View Slide

  90. var o = Imjs.Map({"a": 1,"b": 2});
    // Map {"a": 1, "b": 2}
    var o2 = o.set("a", 3);
    // Map {"a": 3, "b": 2}
    o.get("a"); // 1
    o2.get("a"); // 3

    View Slide

  91. View Slide

  92. var mori = require("mori");
    var a = mori.vector(1,2); // [1 2]
    var a2 = mori.conj(a, 3); // [1 2 3]
    mori.count(a); // 2
    mori.get(a2, 2); // 3

    View Slide

  93. var o = mori.hashMap("a", 1, "b", 2);
    // {"a" 1 "b" 2}
    var o2 = mori.assoc(o, "a", 3);
    // {"a" 3 "b" 2}
    mori.get(o, "a"); // 1
    mori.get(o2, "a"); // 3

    View Slide

  94. immutable.js
    MORI
    vs.
    × JavaScript
    all the way
    × Object-oriented
    API
    × Smaller
    facebook.github.io/immutable-js
    swannodette.github.io/mori
    × ClojureScript
    under the hood
    × Functional API
    × Faster

    View Slide

  95. live long and
    don’t mutate!

    View Slide

  96. thanks!
    @AnjanaVakil
    Icons by EmojiOne
    Template by SlidesCarnival
    Inspiration/curiosity by
    Sal Becker & Recurse Center
    Conference by O’Reilly

    View Slide

  97. J.N. L'orange, Understanding Clojure’s Persistent Vectors, Blog series
    hypirion.com/musings/understanding-persistent-vector-pt-1
    P. Bagwell, Ideal hash trees, 2001 lampwww.epfl.ch/papers/idealhashtrees.pdf
    R. Hickey, Persistent data structures and managed references, QCon 2009
    infoq.com/presentations/Value-Identity-State-Rich-Hickey
    D. Spiewak, Extreme Cleverness: Functional Data Structures in Scala, Strange Loop 2011
    infoq.com/presentations/Functional-Data-Structures-in-Scala
    M. Thatte, What Lies Beneath: A Deep Dive Into Clojure's Data Structures, EuroClojure 2015
    youtu.be/7BFF50BHPPo
    D. Nolen, Immutability, interactivity & Javascript, FutureJS 2014 youtu.be/mS264h8KGwk
    L. Byron, Immutable Data & React, React.js Conf 2015 youtu.be/I7IdS-PbEgI
    References & more

    View Slide