A Lever for the Mind

Cd9b247e4507fed75312e9a42070125d?s=47 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 http://codon.com/a-lever-for-the-mind.

Cd9b247e4507fed75312e9a42070125d?s=128

Tom Stuart

November 19, 2014
Tweet

Transcript

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

  2. Give me a lever long enough and a fulcrum on

    which to place it, and I shall move the world.” — Archimedes “
  3. None
  4. ABSTRACTION

  5. NUMBERS

  6. None
  7. None
  8. None
  9. None
  10. None
  11. None
  12. None
  13. None
  14. None
  15. 3

  16. None
  17. 4 3 2

  18. None
  19. None
  20. None
  21. <

  22. None
  23. None
  24. None
  25. None
  26. None
  27. None
  28. 3

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

  30. 2 3 5 add ABSTRACT

  31. SUMS

  32. 1 + 2 + 3 + 4 + 5 +

    6 + 7 + 8 + 9 + 10 = ?
  33. 1 + 2 = 3 3 + 3 = 6

    6 + 4 = 10 10 + 5 = 15
  34. 15 + 6 = 21 21 + 7 = 28

    28 + 8 = 36 36 + 9 = 45 45 + 10 = 55
  35. 1 + 2 + 3 + 4 + 5 +

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

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

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

    + 8 + 4 + 7 + 5 + 6 =
  39. 11 + 11 + 11 + 11 + 11 =

    ?
  40. 11 + 11 + 11 + 11 + 11 =

    55
  41. 1 + 10 + 2 + 9 + 3 +

    8 + 4 + 7 + 5 + 6 = 55
  42. 1 + 2 + … + 9 + 10 =

    (10 ÷ 2) × (10 + 1)
  43. 1 + 2 + 3 + 4 + 5 +

    … … + 98 + 99 + 100 = ?
  44. 1 + 100 + 2 + 99 + 49 +

    52 + 50 + 51 = ? ⋮
  45. 101 + 101 + 101 + 101 = ? ⋮

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

  47. 1 + 2 + … + 99 + 100 =

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

    2) × (n + 1)
  49. None
  50. None
  51. 10 11

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

    + … + n =
  53. 1 + 2 + … + n = (n +

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

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

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

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

    500,500
  58. GRAPHS

  59. None
  60. None
  61. None
  62. None
  63. None
  64. None
  65. None
  66. None
  67. None
  68. None
  69. None
  70. None
  71. None
  72. 5 3 3 3

  73. None
  74. None
  75. None
  76. None
  77. DEGREE 2

  78. DEGREE 3

  79. WALK

  80. CONNECTED

  81. CONNECTED

  82. CONNECTED

  83. CONNECTED

  84. TRAIL

  85. EULERIAN TRAIL

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

  87. None
  88. TRIANGLES

  89. 4 3 5

  90. 4 4 5.7

  91. 4 5 6.4

  92. 3 5.8 5

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

  94. None
  95. None
  96. None
  97. a² b²

  98. c² a² b²

  99. c² a² b² + =

  100. c² a² b²

  101. c² a² b²

  102. c² a² b²

  103. a b c a² + b² = c²

  104. MATHEMATICS

  105. SPOT PATTERNS, BUILD REUSABLE ABSTRACTIONS

  106. BAD MATHEMATICS EDUCATION

  107. None
  108. None
  109. POKER

  110. HIGH CARD ONE PAIR TWO PAIR

  111. THREE OF A KIND STRAIGHT FLUSH

  112. 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)
  113. Hand = Struct.new(:cards) do include Comparable def <=>(other) # TODO

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

    other.highest_card_rank end # … end
  115. 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
  116. 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
  117. 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
  118. 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
  119. 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
  120. 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
  121. 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)
  122. 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
  123. 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
  124. class << Hand::Category::HIGH_CARD def matches?(hand) true end def compare(a, b)

    # … end end
  125. class << Hand::Category::ONE_PAIR def matches?(hand) pairs(hand).size == 1 end def

    compare(a, b) # … end end
  126. 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
  127. Hand = Struct.new(:cards) do def rank Hand::Rank.new(self) end end if

    my_hand.rank > your_hand.rank puts 'I win!' end
  128. 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
  129. None
  130. None
  131. low high

  132. 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
  133. “DESIGN”?

  134. 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 “
  135. HOW?

  136. FIND THE HONEST ABSTRACTION

  137. FIND THE MINIMAL ABSTRACTION

  138. FIND THE INTERESTING THING INSIDE THE BORING THING

  139. BE EXCITED!

  140. KEEP YOUR PERSPECTIVE

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

  142. SORRY!* * not sorry

  143. THANKS @tomstuart, tom@codon.com, http:/ /codon.com/