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

Ruby: A Family History (no notes)

Ruby: A Family History (no notes)

A talk I gave at Railsconf 2018.

Rails is made possible by Ruby’s unique combination of deep dynamism and pragmatic elegance. In turn, Ruby inherited many of its core ideas from older languages including Lisp, Smalltalk, and Perl.

In this talk, we’ll take a tour of these languages and their myriad influences on Ruby, to better understand the foundations of our tools, improve our ability to use them to their full potential, and imagine how they might be further improved.

Geoffrey Litt

April 18, 2018
Tweet

More Decks by Geoffrey Litt

Other Decks in Technology

Transcript

  1. Ruby:
    A Family History
    Geoffrey Litt
    @geoffreylitt
    Panorama Education

    View Slide

  2. Why do I Ruby?

    View Slide

  3. By learning
    other languages,
    we can broaden
    our horizons and
    also more deeply
    understand
    Ruby.
    — matz

    View Slide

  4. !

    View Slide

  5. View Slide

  6. LISP

    View Slide

  7. Ruby was a Lisp originally,
    in theory.
    Let's call it MatzLisp from
    now on. ;-)
    — matz

    View Slide

  8. View Slide

  9. 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))
    ;...

    View Slide

  10. View Slide

  11. View Slide

  12. View Slide

  13. Functions
    (lambda (x) (* x 2))

    View Slide

  14. Functions
    (map
    (lambda (x) (* x 2))
    (1 2 3))

    View Slide

  15. Functions
    (map
    (lambda (x) (* x 2))
    (1 2 3))
    [1, 2, 3].map(
    &lambda { |x| x * 2 }
    )

    View Slide

  16. Functions
    { |x| x * 2 } # => SyntaxError

    View Slide

  17. Functions
    { |x| x * 2 } # => SyntaxError
    def takes_a_block
    yield 2
    end
    takes_a_block { |x| x * 2 } # => 4

    View Slide

  18. Functions
    (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 }

    View Slide

  19. Functions
    (describe "my machine" (lambda () (
    (it "produces widgets" (lambda () (
    ;...
    ))))))
    describe "my machine" do
    it "produces widgets" do
    #...
    end
    end

    View Slide

  20. Thoughtful inconsistency

    View Slide

  21. Syntax
    (
    (let a 1)
    (let b 2)
    (+ a b))

    View Slide

  22. The project...was neither
    finalized nor explicitly
    abandoned. It just
    receded into the indefinite
    future...
    — John McCarthy

    View Slide

  23. LISP Syntax
    (
    (let a 1)
    (let b 2)
    (+ a b))

    View Slide

  24. FORTRAN Syntax
    a = 1
    b = 2
    result = a + b

    View Slide

  25. Pick your battles.

    View Slide

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

    View Slide

  27. 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))), []]

    View Slide

  28. 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)"

    View Slide

  29. Smalltalk

    View Slide

  30. View Slide

  31. View Slide

  32. View Slide

  33. What is "object-oriented
    programming"?

    View Slide

  34. What is "object-oriented
    programming"?
    What was the original
    intention of object-
    oriented programming?

    View Slide

  35. I could hardly believe how
    beautiful and wonderful
    the idea of LISP was...but
    there were deep flaws in
    its logical foundations.
    — Alan Kay

    View Slide

  36. View Slide

  37. View Slide

  38. View Slide

  39. In computer terms,
    Smalltalk is a recursion on
    the notion of computer
    itself.
    — Alan Kay

    View Slide

  40. Message passing
    3 + 4
    "=> 7

    View Slide

  41. View Slide

  42. View Slide

  43. View Slide

  44. Message passing similarities
    Smalltalk:
    3 perform: '+' asSymbol with: 4
    Ruby:
    3.send(:+, 4)

    View Slide

  45. Message passing similarities
    Smalltalk:
    3 isKindOf: Integer
    Ruby:
    3.is_a? Integer

    View Slide

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

    View Slide

  47. Control flow with message sending
    Smalltalk:
    array do: [ :element | Transcript show: element ]
    Ruby:
    array.each { |element| puts element }

    View Slide

  48. Metaprogramming
    Integer extend [
    doesNotUnderstand: msg [
    'method not defined' printNl
    ]
    ]
    class Integer
    def method_missing(msg)
    puts 'method not defined'
    end
    end

    View Slide

  49. Message passing purity
    (2 + 2 == 5)
    ifTrue: [ Transcript show: 'true'. ]
    ifFalse: [ Transcript show: 'false'. ].

    View Slide

  50. Thoughtful inconsistency

    View Slide

  51. View Slide

  52. View Slide

  53. Pick your battles.

    View Slide

  54. Perl

    View Slide

  55. View Slide

  56. "A program is correct if it
    gets the job done before
    you get fired."

    View Slide

  57. "There's more than one
    way to do it"

    View Slide

  58. "Easy things should be
    easy and hard things
    should be possible"

    View Slide

  59. View Slide

  60. Effortless string interpolation
    $x = 5;
    $msg = "The value is $x now.";

    View Slide

  61. More little details
    —native regex syntax
    —%w array syntax
    —heredocs
    —1_000_000 number syntax

    View Slide

  62. Globals
    $global_variable = 1

    View Slide

  63. Globals
    $$

    View Slide

  64. Globals
    $$ # => 19936
    Process ID!

    View Slide

  65. Weak typing
    print "8" + "1";

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  69. Why do I Ruby?

    View Slide

  70. View Slide

  71. Thanks!
    Twitter: @geoffreylitt

    View Slide