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

Ruby: A Family History

Ruby: A Family History

Ruby blends some of the best ideas from older programming languages including Smalltalk, Perl, Lisp, and Ada. In this talk, we’ll take a tour of these languages and their influences on Ruby, to better understand Ruby’s core ideas and how we can use it to its full potential.

7a6310a990212e2b392d95a67855afc2?s=128

Geoffrey Litt

December 12, 2017
Tweet

Transcript

  1. Ruby: A Family History

  2. Why learn many programming languages?

  3. By learning other languages, we can broaden our horizons and

    also more deeply understand Ruby. — matz
  4. None
  5. LISP

  6. Ruby was a Lisp originally, in theory. Let's call it

    MatzLisp from now on. ;-) — Matz
  7. None
  8. Expressions () (foo bar) (1 (2 3) (4 5))

  9. 7 primitive operators —quote —atom —eq —car —cdr —cons —cond

  10. quote (quote foo) ;=> foo 'foo ;=> foo

  11. Lisp primitives: atom (atom 'foo) ;=> t (atom '(a b

    c)) ;=> ()
  12. Lisp primitives: eq (eq 'foo 'foo) ;=> t (eq 'foo

    'bar) ;=> ()
  13. Why we need quote (atom (eq 'foo 'foo)) ;=> t

    (atom '(eq 'foo 'foo)) ;=> ()
  14. Lisp primitives: car (car '(foo bar baz)) ;=> foo

  15. Lisp primitives: cdr (cdr '(foo bar baz)) ;=> (bar baz)

  16. Lisp primitives: cons (cons 'foo '(bar baz)) ;=> (foo bar

    baz)
  17. Lisp primitives: cond (cond ((eq 'foo 'bar) 'first ((eq 'foo

    'foo) 'second)) ;=> second
  18. Defining functions (lambda (arg1) (eq arg1 'foo))

  19. 7 primitive operators + function definition —quote —atom —eq —car

    —cdr —cons —cond —lambda
  20. An interpreter (defun eval (e a) (cond ((atom e) (assoc.

    e a)) ((atom (car e)) (cond ((eq (car e) 'quote) (cadr e)) ((eq (car e) 'atom) (atom (eval (cadr e) a))) ((eq (car e) 'eq) (eq (eval (cadr e) a) (eval (caddr e) a))) ((eq (car e) 'car) (car (eval (cadr e) a))) ((eq (car e) 'cdr) (cdr (eval (cadr e) a))) ((eq (car e) 'cons) (cons (eval (cadr e) a) (eval (caddr e) a))) ((eq (car e) 'cond) (evcon. (cdr e) a)) ;...
  21. None
  22. None
  23. None
  24. FORTRAN syntax a = 12.0 b = 15.0 result =

    a + b print *, 'The total is ', result
  25. The project...was neither finalized nor explicitly abandoned. It just receded

    into the indefinite future... — John McCarthy
  26. Lisp firsts —conditionals —dynamic typing —garbage collection —symbol types

  27. Functions in Lisp (lambda (x) (* x 2))

  28. Functions in Lisp (map (lambda (x) (* x 2)) (1

    2 3))
  29. Functions in Lisp (map (lambda (x) (* x 2)) (1

    2 3)) [1, 2, 3].map( &lambda { |x| x * 2 } )
  30. Functions in Ruby my_fun = lambda { |x| x *

    2 } # => Proc def takes_a_lambda(fun) fun.call(2) end takes_a_lambda(my_fun) # => 4
  31. Functions in Ruby { |x| x * 2 } #

    => SyntaxError def takes_a_block yield 2 end takes_a_block { |x| x * 2 } # => 4
  32. Concise lambdas (map (1 2 3) (lambda (x) (* x

    2))) [1, 2, 3].map { |x| x * 2 }
  33. Concise lambdas (remove-if (lambda (n) (< n 4)) (map (lambda

    (x) (* x 2)) (1 2 3))) [1, 2, 3]. map { |x| x * 2 }. reject{ |n| n < 4 }
  34. Concise lambdas (describe "my machine" (lambda () ( (it "produces

    widgets" (lambda () ( ;... )))))) describe "my machine" do it "produces widgets" do #... end end
  35. Multiple function arguments (even-odd-map (lambda (x) (* x 2)) (lambda

    (x) (* x 3)) (1 2 3 4)) [1, 2, 3, 4].even_odd_map( lambda { |x| x * 2 }, lambda { |x| x * 3 }, )
  36. Lisp is consistent Ruby is pragmatic

  37. Concise lambdas catching on Ruby 1.9+: lambda { |x| x

    * 2 } ->(x) { x * 2 }
  38. Concise lambdas catching on Javascipt ES6: array.map(function(x) { x *

    2 }) array.map(x => x * 2)
  39. Concise lambdas catching on Scala: array.map(_ * 2) array.map(2*)

  40. Metaprogramming

  41. Macros #define square(x) x*x

  42. Macros #define square(x) x*x 2/square(10) 2/10*10

  43. Macros #define square(x) ( (x) * (x) )

  44. Macros (+ 1 2)

  45. Macros (defmacro (backwards . body) (cons 'begin (reverse body)))

  46. Macros (defmacro (backwards . body) (cons 'begin (reverse body))) #

    Fake Ruby macro syntax defmacro backwards(code) code.reverse end
  47. Ruby parsing/unparsing code = "2 + 3 * 4" ast

    = Parser::CurrentRuby.parse(code)
  48. Ruby parsing/unparsing code = "2 + 3 * 4" ast

    = Parser::CurrentRuby.parse(code) # => [s(:send, # s(:int, 2), :+, # s(:send, # s(:int, 3), :*, # s(:int, 4))), []]
  49. Ruby parsing/unparsing code = "2 + 3 * 4" ast

    = Parser::CurrentRuby.parse(code) # => [s(:send, # s(:int, 2), :+, # s(:send, # s(:int, 3), :*, # s(:int, 4))), []] 2.1.5 :005 > Unparser.unparse(ast) # => "2 + (3 * 4)"
  50. Ruby metaprogramming define_method instance_eval class_eval method_missing

  51. Smalltalk

  52. What is "object-oriented programming"? inheritance polymorphism UML diagrams class hierarchies

    factories
  53. None
  54. I could hardly believe how beautiful and wonderful the idea

    of LISP was...but there were deep flaws in its logical foundations. — Alan Kay
  55. None
  56. None
  57. None
  58. In computer terms, Smalltalk is a recursion on the notion

    of computer itself. — Alan Kay
  59. Message passing 3 + 4 "=> 7

  60. None
  61. None
  62. None
  63. Message passing similarities Smalltalk: 3 perform: '+' asSymbol with: 4

    Ruby: 3.send(:+, 4)
  64. Message passing similarities Smalltalk: 3 isKindOf: Integer Ruby: 3.is_a? Integer

  65. Message passing similarities Smalltalk: Integer isKindOf: Class Ruby: Integer.is_a? Class

  66. Message passing similarities Integer extend [ doesNotUnderstand: msg [ 'method

    not defined' printNl ] ] class Integer def method_missing(msg) puts 'method not defined' end end
  67. Control flow with message sending Smalltalk: array do: [ :element

    | Transcript show: element ] Ruby: array.each { |element| puts element }
  68. Message passing purity (2 + 2 == 5) ifTrue: [

    Transcript show: 'true'. ] ifFalse: [ Transcript show: 'false'. ].
  69. None
  70. None
  71. None
  72. A brief aside: Other OO languages Not many people know

    this, but before I created Ruby, as a student I was an advocate for statically typed OO langauges. — Matz
  73. A brief aside: Other OO languages —Ada: 1977-83 —Eiffel: 1985

    Important features —Multiple inheritance —Generics
  74. None
  75. "A program is correct if it gets the job done

    before you get fired." -- Larry Wall
  76. Variable sigils $scalar @array %hash &subroutine *typeglob

  77. The easiest string interpolation $x = 5; $msg = "The

    value is $x now.";
  78. Weak typing print "8" + "1";

  79. Weak typing print "8" + "1"; # => 9

  80. Weak typing @cities = qw( Berlin Tokyo London Boston );

    # Assign the array to a scalar $cities_count = @cities;
  81. Weak typing @cities = qw( Berlin Tokyo London Boston );

    # Assign the array to a scalar $cities_count = @cities; # => 4
  82. Little Perl niceties —native regex syntax —%w array syntax —heredocs

    —1_000_000 number syntax
  83. Perl-inspired oddities $global_variable = 1

  84. Perl-inspired oddities $$

  85. Perl-inspired oddities $$ # => 19936 Process ID!

  86. Perl-inspired oddities $/

  87. Perl-inspired oddities $/ # => "\n" Input record separator, obviously

  88. Perl-inspired oddities /([a-zA-Z]*)/ =~ string match_contents = $1

  89. Perl-inspired oddities END { puts "RB!" } puts "Boston" BEGIN

    { puts "Hello" }
  90. Perl-inspired oddities END { puts "RB!" } puts "Boston" BEGIN

    { puts "Hello" } # Hello # Boston # RB!
  91. Perl mantras "There's more than one way to do it"

  92. Perl mantras "Easy things should be easy and hard things

    should be possible"
  93. What is Ruby? Two elegant theoretical foundations + a big

    dose of practicality
  94. Thanks! @geoffreylitt