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

A Lever for the Mind

Tom Stuart
November 19, 2014

A Lever for the Mind

Humans are the cleverest animals in the known universe. But our brains, forged over millions of years in the unforgiving furnace of natural selection, are still primitive. They evolved to be good at hunting animals, making tools, recognising facial expressions and maintaining social bonds, but they’re just not very good at working with several difficult ideas simultaneously, and they’re particularly bad at reasoning about the counterintuitive emergent behaviour of complex non-human systems.

That’s a problem, because complex non-human systems now dominate our world.

Abstraction is our solution to this problem. Abstraction works as an adapter between the fearsome complexity of the universe and our simple primate minds; when the real world is too detailed, too confusing or too counterintuitive for us to work with directly, abstraction gives us big friendly levers to pull on instead. This one powerful idea underlies computers, design, culture, language, and everything else we rely on in our daily work.

This is a talk about abstraction: where it comes from, what it’s for, and how we can use it to make our programs better.

Given at RubyConf 2014 (http://lanyrd.com/2014/rubyconf/) and Bath Ruby Conference 2015 (http://2015.bathruby.org/). A video and transcript is available at https://tomstu.art/a-lever-for-the-mind.

Tom Stuart

November 19, 2014
Tweet

More Decks by Tom Stuart

Other Decks in Programming

Transcript

  1. THE
    A LEVER
    FOR
    MIND
    @tomstuart at RubyConf on 2014-11-19

    View Slide

  2. Give me a lever long enough
    and a fulcrum on which to place it,
    and I shall move the world.”
    — Archimedes

    View Slide

  3. View Slide

  4. ABSTRACTION

    View Slide

  5. NUMBERS

    View Slide

  6. View Slide

  7. View Slide

  8. View Slide

  9. View Slide

  10. View Slide

  11. View Slide

  12. View Slide

  13. View Slide

  14. View Slide

  15. 3

    View Slide

  16. View Slide

  17. 4
    3
    2

    View Slide

  18. View Slide

  19. View Slide

  20. View Slide

  21. <

    View Slide

  22. View Slide

  23. View Slide

  24. View Slide

  25. View Slide

  26. View Slide

  27. View Slide

  28. 3

    View Slide

  29. 2
    3 5
    combine
    add
    count count count
    REAL
    ABSTRACT

    View Slide

  30. 2
    3 5
    add
    ABSTRACT

    View Slide

  31. SUMS

    View Slide

  32. 1 + 2 + 3 + 4 + 5 +
    6 + 7 + 8 + 9 + 10 = ?

    View Slide

  33. 1 + 2 = 3
    3 + 3 = 6
    6 + 4 = 10
    10 + 5 = 15

    View Slide

  34. 15 + 6 = 21
    21 + 7 = 28
    28 + 8 = 36
    36 + 9 = 45
    45 + 10 = 55

    View Slide

  35. 1 + 2 + 3 + 4 + 5 +
    6 + 7 + 8 + 9 + 10 = 55

    View Slide

  36. 1 + 2 + 3 + 4 + 5 + …
    … + 98 + 99 + 100 = ?

    View Slide

  37. ?
    1 + 2 +
    3 + 4 +
    5 + 6 +
    7 + 8 +
    9 + 10 =

    View Slide

  38. ?
    1 + 10 +
    2 + 9 +
    3 + 8 +
    4 + 7 +
    5 + 6 =

    View Slide

  39. 11 +
    11 +
    11 +
    11 +
    11 = ?

    View Slide

  40. 11 +
    11 +
    11 +
    11 +
    11 = 55

    View Slide

  41. 1 + 10 +
    2 + 9 +
    3 + 8 +
    4 + 7 +
    5 + 6 = 55

    View Slide

  42. 1 + 2 + … + 9 + 10 =
    (10 ÷ 2) × (10 + 1)

    View Slide

  43. 1 + 2 + 3 + 4 + 5 + …
    … + 98 + 99 + 100 = ?

    View Slide

  44. 1 + 100 +
    2 + 99 +
    49 + 52 +
    50 + 51 = ?

    View Slide

  45. 101 +
    101 +
    101 +
    101 = ?

    View Slide

  46. 101 +
    101 +
    101 +
    101 = 5,050

    View Slide

  47. 1 + 2 + … + 99 + 100 =
    (100 ÷ 2) × (100 + 1)

    View Slide

  48. 1 + 2 + … + n =
    (n ÷ 2) × (n + 1)

    View Slide

  49. View Slide

  50. View Slide

  51. 10
    11

    View Slide

  52. (n + 1) × n ÷ 2
    1 + 2 + … + n =

    View Slide

  53. 1 + 2 + … + n =
    (n + 1)
    ×
    n ÷ 2
    ( )

    View Slide

  54. 1 + 2 + … + 999 + 1000 =
    ?

    View Slide

  55. 1 + 2 + … + 999 + 1000 =
    (1000 ÷ 2) × (1000 + 1)

    View Slide

  56. 1 + 2 + … + 999 + 1000 =
    500 × 1001

    View Slide

  57. 1 + 2 + … + 999 + 1000 =
    500,500

    View Slide

  58. GRAPHS

    View Slide

  59. View Slide

  60. View Slide

  61. View Slide

  62. View Slide

  63. View Slide

  64. View Slide

  65. View Slide

  66. View Slide

  67. View Slide

  68. View Slide

  69. View Slide

  70. View Slide

  71. View Slide

  72. 5
    3
    3
    3

    View Slide

  73. View Slide

  74. View Slide

  75. View Slide

  76. View Slide

  77. DEGREE
    2

    View Slide

  78. DEGREE
    3

    View Slide

  79. WALK

    View Slide

  80. CONNECTED

    View Slide

  81. CONNECTED

    View Slide

  82. CONNECTED

    View Slide

  83. CONNECTED

    View Slide

  84. TRAIL

    View Slide

  85. EULERIAN TRAIL

    View Slide

  86. EULERIAN TRAIL
    CONNECTED
    OF ODD DEGREE
    AT MOST 2 NODES

    View Slide

  87. View Slide

  88. TRIANGLES

    View Slide

  89. 4
    3
    5

    View Slide

  90. 4
    4
    5.7

    View Slide

  91. 4
    5
    6.4

    View Slide

  92. 3
    5.8
    5

    View Slide

  93. a
    b
    c a² + b² = c²

    View Slide

  94. View Slide

  95. View Slide


  96. View Slide

  97. View Slide



  98. View Slide




  99. View Slide


  100. a² b²
    + =

    View Slide




  101. View Slide




  102. View Slide




  103. View Slide

  104. a
    b
    c a² + b² = c²

    View Slide

  105. MATHEMATICS

    View Slide

  106. SPOT PATTERNS,
    BUILD REUSABLE
    ABSTRACTIONS

    View Slide

  107. BAD
    MATHEMATICS
    EDUCATION

    View Slide

  108. View Slide

  109. View Slide

  110. POKER

    View Slide

  111. HIGH CARD
    ONE PAIR
    TWO PAIR

    View Slide

  112. THREE OF
    A KIND
    STRAIGHT
    FLUSH

    View Slide

  113. Card = Struct.new(:rank, :suit)
    three_of_diamonds = Card.new(3, :diamonds)
    queen_of_hearts = Card.new(12, :hearts)
    ace_of_spades = Card.new(14, :spades)

    View Slide

  114. Hand = Struct.new(:cards) do
    include Comparable
    def <=>(other)
    # TODO
    end
    end

    View Slide

  115. Hand = Struct.new(:cards) do
    include Comparable
    def <=>(other)
    highest_card_rank <=> other.highest_card_rank
    end
    # …
    end

    View Slide

  116. Hand = Struct.new(:cards) do
    include Comparable
    def <=>(other)
    if highest_card_rank == other.highest_card_rank
    without { |c| c.rank == highest_card_rank } <=>
    other.without { |c| c.rank == highest_card_rank }
    else
    highest_card_rank <=> other.highest_card_rank
    end
    end
    # …
    end

    View Slide

  117. Hand = Struct.new(:cards) do
    include Comparable
    def <=>(other)
    if empty? && other.empty?
    0
    elsif highest_card_rank == other.highest_card_rank
    without { |c| c.rank == highest_card_rank } <=>
    other.without { |c| c.rank == highest_card_rank }
    else
    highest_card_rank <=> other.highest_card_rank
    end
    end
    # …
    end

    View Slide

  118. Hand = Struct.new(:cards) do
    include Comparable
    def <=>(other)
    if one_pair?
    if other.one_pair?
    if highest_pair_rank == other.highest_pair_rank
    without { |c| c.rank == highest_pair_rank } <=>
    other.without { |c| c.rank == highest_pair_rank }
    else
    highest_pair_rank <=> other.highest_pair_rank
    end
    else
    1
    end
    else
    if empty? && other.empty?
    0
    elsif other.one_pair?
    -1
    elsif highest_card_rank == other.highest_card_rank
    without { |c| c.rank == highest_card_rank } <=>
    other.without { |c| c.rank == highest_card_rank }
    else
    highest_card_rank <=> other.highest_card_rank
    end
    end
    end
    # …
    end

    View Slide

  119. Hand = Struct.new(:cards) do
    include Comparable
    def <=>(other)
    if two_pair?
    if other.two_pair?
    if highest_pair_rank == other.highest_pair_rank
    without { |c| c.rank == highest_pair_rank } <=>
    other.without { |c| c.rank == highest_pair_rank }
    else
    highest_pair_rank <=> other.highest_pair_rank
    end
    else
    1
    end
    elsif one_pair?
    if other.two_pair?
    -1
    elsif other.one_pair?
    if highest_pair_rank == other.highest_pair_rank
    without { |c| c.rank == highest_pair_rank } <=>
    other.without { |c| c.rank == highest_pair_rank }
    else
    highest_pair_rank <=> other.highest_pair_rank
    end
    else
    1
    end
    else
    if empty? && other.empty?
    0
    elsif other.one_pair? || other.two_pair?
    -1
    elsif highest_card_rank == other.highest_card_rank
    without { |c| c.rank == highest_card_rank } <=>
    other.without { |c| c.rank == highest_card_rank }
    else
    highest_card_rank <=> other.highest_card_rank
    end
    end
    end
    # …
    end

    View Slide

  120. Hand = Struct.new(:cards) do
    include Comparable
    def <=>(other)
    if three_of_a_kind?
    if other.three_of_a_kind?
    if highest_triple_rank == other.highest_triple_rank
    without { |c| c.rank == highest_triple_rank } <=>
    other.without { |c| c.rank == highest_triple_rank }
    else
    highest_triple_rank <=> other.highest_triple_rank
    end
    else
    1
    end
    elsif two_pair?
    if other.three_of_a_kind?
    -1
    elsif other.two_pair?
    if highest_pair_rank == other.highest_pair_rank
    without { |c| c.rank == highest_pair_rank } <=>
    other.without { |c| c.rank == highest_pair_rank }
    else
    highest_pair_rank <=> other.highest_pair_rank
    end
    else
    1
    end
    elsif one_pair?
    if other.two_pair? || other.three_of_a_kind?
    -1
    elsif other.one_pair?
    if highest_pair_rank == other.highest_pair_rank
    without { |c| c.rank == highest_pair_rank } <=>
    other.without { |c| c.rank == highest_pair_rank }
    else
    highest_pair_rank <=> other.highest_pair_rank
    end
    else
    1
    end
    else
    if empty? && other.empty?
    0
    elsif other.one_pair? || other.two_pair? || other.three_of_a_kind?
    -1
    elsif highest_card_rank == other.highest_card_rank
    without { |c| c.rank == highest_card_rank } <=>
    other.without { |c| c.rank == highest_card_rank }
    else
    highest_card_rank <=> other.highest_card_rank
    end
    end
    end
    # …
    end

    View Slide

  121. Hand = Struct.new(:cards) do
    include Comparable
    def <=>(other)
    if straight?
    if other.straight?
    if highest_straight_rank == other.highest_straight_rank
    without { |c| c.rank == highest_straight_rank } <=>
    other.without { |c| c.rank == highest_straight_rank }
    else
    highest_straight_rank <=> other.highest_straight_rank
    end
    else
    1
    end
    elsif three_of_a_kind?
    if other.straight?
    -1
    elsif other.three_of_a_kind?
    if highest_triple_rank == other.highest_triple_rank
    without { |c| c.rank == highest_triple_rank } <=>
    other.without { |c| c.rank == highest_triple_rank }
    else
    highest_triple_rank <=> other.highest_triple_rank
    end
    else
    1
    end
    elsif two_pair?
    if other.three_of_a_kind? || other.straight?
    -1
    elsif other.two_pair?
    if highest_pair_rank == other.highest_pair_rank
    without { |c| c.rank == highest_pair_rank } <=>
    other.without { |c| c.rank == highest_pair_rank }
    else
    highest_pair_rank <=> other.highest_pair_rank
    end
    else
    1
    end
    elsif one_pair?
    if other.two_pair? || other.three_of_a_kind? || other.straight?
    -1
    elsif other.one_pair?
    if highest_pair_rank == other.highest_pair_rank
    without { |c| c.rank == highest_pair_rank } <=>
    other.without { |c| c.rank == highest_pair_rank }
    else
    highest_pair_rank <=> other.highest_pair_rank
    end
    else
    1
    end
    else
    if empty? && other.empty?
    0
    elsif other.one_pair? || other.two_pair? || other.three_of_a_kind? || other.straight?
    -1
    elsif highest_card_rank == other.highest_card_rank
    without { |c| c.rank == highest_card_rank } <=>
    other.without { |c| c.rank == highest_card_rank }
    else
    highest_card_rank <=> other.highest_card_rank
    end
    end
    end
    # …
    end

    View Slide

  122. Card = Struct.new(:rank, :suit)
    class Card::Rank
    TWO, THREE, FOUR, FIVE,
    SIX, SEVEN, EIGHT, NINE,
    TEN, JACK, QUEEN, KING, ACE = 13.times.map { new }
    end
    class Card::Suit
    CLUBS, HEARTS, SPADES, DIAMONDS = 4.times.map { new }
    end
    three_of_diamonds = Card.new(Card::Rank::THREE, Card::Suit::DIAMONDS)
    queen_of_hearts = Card.new(Card::Rank::QUEEN, Card::Suit::HEARTS)
    ace_of_spades = Card.new(Card::Rank::ACE, Card::Suit::SPADES)

    View Slide

  123. class Card::Rank
    include Comparable
    ORDER = (
    TWO, THREE, FOUR, FIVE,
    SIX, SEVEN, EIGHT, NINE,
    TEN, JACK, QUEEN, KING, ACE = 13.times.map { new }
    )
    def <=>(other)
    ORDER.index(self) <=> ORDER.index(other)
    end
    end

    View Slide

  124. class Hand::Category
    include Comparable
    ORDER = (
    HIGH_CARD, ONE_PAIR, TWO_PAIR, THREE_OF_A_KIND,
    STRAIGHT, FLUSH, FULL_HOUSE, FOUR_OF_A_KIND,
    STRAIGHT_FLUSH = 9.times.map { new }
    )
    def <=>(other)
    ORDER.index(self) <=> ORDER.index(other)
    end
    end

    View Slide

  125. class << Hand::Category::HIGH_CARD
    def matches?(hand)
    true
    end
    def compare(a, b)
    # …
    end
    end

    View Slide

  126. class << Hand::Category::ONE_PAIR
    def matches?(hand)
    pairs(hand).size == 1
    end
    def compare(a, b)
    # …
    end
    end

    View Slide

  127. Hand::Rank = Struct.new(:hand) do
    include Comparable
    def category
    Hand::Category::ORDER.
    select { |category| category.matches?(hand) }.max
    end
    def <=>(other)
    if category == other.category
    category.compare(hand, other.hand)
    else
    category <=> other.category
    end
    end
    end

    View Slide

  128. Hand = Struct.new(:cards) do
    def rank
    Hand::Rank.new(self)
    end
    end
    if my_hand.rank > your_hand.rank
    puts 'I win!'
    end

    View Slide

  129. class Card::Rank
    ORDER = (
    TWO, THREE, FOUR, FIVE,
    SIX, SEVEN, EIGHT, NINE,
    TEN, JACK, QUEEN, KING, ACE = 13.times.map { new }
    )
    def succ
    ORDER[ORDER.index(self).succ]
    end
    end

    View Slide

  130. View Slide

  131. View Slide

  132. low
    high

    View Slide

  133. class Card::Rank
    ORDER = (
    TWO, THREE, FOUR, FIVE,
    SIX, SEVEN, EIGHT, NINE,
    TEN, JACK, QUEEN, KING, ACE = 13.times.map { new }
    )
    def succ
    ORDER[ORDER.index(self).succ % ORDER.size]
    end
    end

    View Slide

  134. “DESIGN”?

    View Slide

  135. When a thing looks complicated,
    it’s possible that we’re looking at
    it wrong and missing some of the
    pieces of the puzzle.”
    — Richard Feynman

    View Slide

  136. HOW?

    View Slide

  137. FIND THE
    HONEST
    ABSTRACTION

    View Slide

  138. FIND THE
    MINIMAL
    ABSTRACTION

    View Slide

  139. FIND THE
    INTERESTING THING
    INSIDE THE
    BORING THING

    View Slide

  140. BE EXCITED!

    View Slide

  141. KEEP YOUR
    PERSPECTIVE

    View Slide

  142. IF YOU CAN
    WRITE A PROGRAM,
    YOU’RE GOOD
    AT MATHEMATICS.

    View Slide

  143. SORRY!*
    * not sorry

    View Slide

  144. THANKS
    @tomstuart, [email protected], http:/
    /codon.com/

    View Slide