Writing your own Programming Language to understand Ruby better

Writing your own Programming Language to understand Ruby better

@GoGaRuCo 2011

7c12adb8b5521c060ab4630360a4fa27?s=128

Plataformatec

March 02, 2012
Tweet

Transcript

  1. José Valim @josevalim blog.plataformatec.com Writing your own Programming Language to

    Understand Ruby sexta-feira, 2 de março de 12
  2. blog twitter ID José Valim @josevalim blog.plataformatec.com Writing your own

    Programming Language to Understand Ruby sexta-feira, 2 de março de 12
  3. Elixir Simple Object Orientation and charming syntax on top of

    Erlang sexta-feira, 2 de março de 12
  4. Erlang VM + Concurrent Processes + Message Based + Hot

    Code Swapping + Runs with low memory sexta-feira, 2 de março de 12
  5. Erlang Language + Small and quick to learn + Functional

    programming - Syntax gets too much in your way - No object orientation sexta-feira, 2 de março de 12
  6. Elixir Simple Object Orientation and charming syntax on top of

    Erlang sexta-feira, 2 de março de 12
  7. <3 Ruby <3 sexta-feira, 2 de março de 12

  8. sexta-feira, 2 de março de 12

  9. @tenderl—ve sexta-feira, 2 de março de 12

  10. * Things I learned about Ruby sexta-feira, 2 de março

    de 12
  11. Things I learned about sexta-feira, 2 de março de 12

  12. The Syntax sexta-feira, 2 de março de 12

  13. puts sexta-feira, 2 de março de 12

  14. puts Lexe sexta-feira, 2 de março de 12

  15. puts Lexe [:identifier, “puts”], sexta-feira, 2 de março de 12

  16. puts Lexe [:identifier, “puts”], Parse sexta-feira, 2 de março de

    12
  17. puts Lexe [:identifier, “puts”], [:call, “puts”,[ [:string, Parse sexta-feira, 2

    de março de 12
  18. puts Lexe [:identifier, “puts”], [:call, “puts”,[ [:string, Parse Semanti c

    sexta-feira, 2 de março de 12
  19. puts Lexe [:identifier, “puts”], [:call, “puts”,[ [:string, Parse Semanti c

    [:call, “puts”,[ [:string, sexta-feira, 2 de março de 12
  20. puts Lexe [:identifier, “puts”], [:call, “puts”,[ [:string, Parse Semanti c

    [:call, “puts”,[ [:string, Native / Bytecod sexta-feira, 2 de março de 12
  21. puts Lexe [:identifier, “puts”], [:call, “puts”,[ [:string, Parse Semanti c

    [:call, “puts”,[ [:string, Native / Bytecod sexta-feira, 2 de março de 12
  22. Flexible Grammar sexta-feira, 2 de março de 12

  23. def foo 1 end foo #=> 1 self.foo #=> 1

    sexta-feira, 2 de março de 12
  24. def foo 1 end foo #=> 1 self.foo #=> 1

    foo = 2 foo #=> 2 self.foo #=> 1 sexta-feira, 2 de março de 12
  25. foo sexta-feira, 2 de março de 12

  26. foo Lexe sexta-feira, 2 de março de 12

  27. foo Lexe [:identifier, “foo”] sexta-feira, 2 de março de 12

  28. foo Lexe [:identifier, “foo”] Parse sexta-feira, 2 de março de

    12
  29. foo Lexe [:identifier, “foo”] [:identifier, Parse sexta-feira, 2 de março

    de 12
  30. foo Lexe [:identifier, “foo”] [:identifier, Parse Semanti c sexta-feira, 2

    de março de 12
  31. foo Lexe [:identifier, “foo”] [:identifier, Parse Semanti c ? sexta-feira,

    2 de março de 12
  32. foo Lexe [:identifier, “foo”] [:identifier, Parse Semanti c Native /

    Bytecod ? sexta-feira, 2 de março de 12
  33. def bar foo = 1 foo end sexta-feira, 2 de

    março de 12
  34. def bar foo = 1 foo end [:method,:bar,[ [:assign, "foo",

    [:integer,1]], [:identifier,"foo"] ]] lexer + parser sexta-feira, 2 de março de 12
  35. def bar foo = 1 foo end [:method,:bar,[ [:assign, "foo",

    [:integer,1]], [:identifier,"foo"] ]] lexer + parser [:method,:bar,[ [:assign, "foo", [:integer,1]], [:var,"foo"] ]] semantic analysis sexta-feira, 2 de março de 12
  36. sexta-feira, 2 de março de 12

  37. def bar(arg) arg.class end bar /foo/m sexta-feira, 2 de março

    de 12
  38. def bar(arg) arg.class end bar /foo/m bar, foo, m =

    0, 1, 2 bar /foo/m sexta-feira, 2 de março de 12
  39. sexta-feira, 2 de março de 12

  40. sexta-feira, 2 de março de 12

  41. def show @user = User.find(self.params[:id]) if @user.name =~ %r/^Ph\.D/i self.render

    :action => "show" else self.flash[:notice] = "Ph.D required" self.redirect_to "/" end end sexta-feira, 2 de março de 12
  42. def show @user = User.find(params[:id]) if @user.name =~ /^Ph\.D/i render

    :action => "show" else flash[:notice] = "Ph.D required" redirect_to "/" end end sexta-feira, 2 de março de 12
  43. Trivia sexta-feira, 2 de março de 12

  44. Trivia array = [1,2,3] sexta-feira, 2 de março de 12

  45. Trivia array = [1,2,3] array.length+1 sexta-feira, 2 de março de

    12
  46. Trivia array = [1,2,3] array.length+1 #=> 4 sexta-feira, 2 de

    março de 12
  47. Trivia array = [1,2,3] array.length+1 #=> 4 array.length +1 sexta-feira,

    2 de março de 12
  48. Trivia array = [1,2,3] array.length+1 #=> 4 array.length +1 #=>

    ArgumentError sexta-feira, 2 de março de 12
  49. Trivia array = [1,2,3] array.length+1 #=> 4 array.length +1 #=>

    ArgumentError array.length + 1 sexta-feira, 2 de março de 12
  50. Trivia array = [1,2,3] array.length+1 #=> 4 array.length +1 #=>

    ArgumentError array.length + 1 #=> 4 sexta-feira, 2 de março de 12
  51. Trivia p { } p { a: 1 } Is

    it a block or a sexta-feira, 2 de março de 12
  52. The Object sexta-feira, 2 de março de 12

  53. object = Object.new def object.greet(name) puts "Hello #{name}" end object.greet("Matz")

    sexta-feira, 2 de março de 12
  54. Ruby methods are stored in modules sexta-feira, 2 de março

    de 12
  55. module Greeter def greet(name) "Hello #{name}" end end class Person

    include Greeter end Person.new.greet "Matz" sexta-feira, 2 de março de 12
  56. class Person def greet(name) "Hello #{name}" end end Person.new.greet "Matz"

    sexta-feira, 2 de março de 12
  57. Person.is_a?(Module) #=> true Class.superclass #=> Module sexta-feira, 2 de março

    de 12
  58. object = Object.new def object.greet(name) puts "Hello #{name}" end object.greet("Matz")

    sexta-feira, 2 de março de 12
  59. object.class.ancestors #=> [Object, Kernel, BasicObject] sexta-feira, 2 de março de

    12
  60. object.class.ancestors #=> [Object, Kernel, BasicObject] object.class.ancestors.any? do |r| r.method_defined?(:greet) end

    #=> false sexta-feira, 2 de março de 12
  61. object.class.ancestors #=> [Object, Kernel, BasicObject] object.class.ancestors.any? do |r| r.method_defined?(:greet) end

    #=> false object.singleton_class. method_defined?(:greet) #=> true sexta-feira, 2 de março de 12
  62. object.class.ancestors #=> [Object, Kernel, BasicObject] object.class.ancestors.any? do |r| r.method_defined?(:greet) end

    #=> false object.singleton_class. method_defined?(:greet) #=> true object.singleton_class.is_a?(Module) #=> true sexta-feira, 2 de março de 12
  63. _why once said: Creating your own programming language is fun

    if you can keep it Trivia sexta-feira, 2 de março de 12
  64. Ruby’s parse.y is more than 10k LOC Trivia sexta-feira, 2

    de março de 12
  65. What if? sexta-feira, 2 de março de 12

  66. ... we did not have blocks? sexta-feira, 2 de março

    de 12
  67. <3 Blocks sexta-feira, 2 de março de 12

  68. File.open "gogaruco.txt" do |f| f.write "doing it live" end sexta-feira,

    2 de março de 12
  69. File.open "gogaruco.txt", do |f| f.write "doing it live" end sexta-feira,

    2 de março de 12
  70. File.open "gogaruco.txt", do |f| f.write "doing it live" end sexta-feira,

    2 de março de 12
  71. File.open("gogaruco.txt", do |f| f.write "doing it live" end) sexta-feira, 2

    de março de 12
  72. do_it = do |f| f.write "doing it live" end File.open

    "gogaruco.txt", do_it sexta-feira, 2 de março de 12
  73. No blocks + No need for yield, &block + Passing

    more than one block around is more natural sexta-feira, 2 de março de 12
  74. ... we had Array and Hash comprehensions sexta-feira, 2 de

    março de 12
  75. n = [1,2,3,4] [x * 2 for x in n]

    # => [2,4,6,8] sexta-feira, 2 de março de 12
  76. n = [1,2,3] [x * 2 for x in n,

    x.odd?] # => [2,6] sexta-feira, 2 de março de 12
  77. n = [1,2,3,4] [[x,y] for x in n, y in

    n, x * x == y] # => [[1,1],[2,4]] sexta-feira, 2 de março de 12
  78. n = [1,2,3,4] {x => y for x in n,

    y in n, x * x == y} # => { 1 => 1, 2 => 4 } sexta-feira, 2 de março de 12
  79. ... our hashes were more like sexta-feira, 2 de março

    de 12
  80. { a: 1 } sexta-feira, 2 de março de 12

  81. { "a": 1 } sexta-feira, 2 de março de 12

  82. Trivia { "a-b": 1 } == { :"a-b" => 1

    } sexta-feira, 2 de março de 12
  83. ... we had (better)pattern sexta-feira, 2 de março de 12

  84. x, y, *z = [1,2,3,4,5] x #=> 1 y #=>

    2 z #=> [3,4,5] sexta-feira, 2 de março de 12
  85. x, [y1,*y2], *z = [1,[2,3,4],5] x #=> 1 y1 #=>

    2 y2 #=> [3,4] z #=> [5] sexta-feira, 2 de março de 12
  86. x, x, *z = [1,2,3,4,5] #=> Raises an error sexta-feira,

    2 de março de 12
  87. x, x, *z = [1,1,3,4,5] #=> Works! sexta-feira, 2 de

    março de 12
  88. x = 1 ^x, *y = [3, 2, 1] #=>

    Raises an error! ^x, *y = [1, 2, 3] # => Works! sexta-feira, 2 de março de 12
  89. def form_for(object) case object when Hash # ... when Array

    # ... else # ... end end sexta-feira, 2 de março de 12
  90. def form_for(record : Hash) # ... end def form_for(record :

    Array) # ... end def form_for(record) # ... end sexta-feira, 2 de março de 12
  91. + Better to maintain + Better to document - No

    duck typing Method pattern matching sexta-feira, 2 de março de 12
  92. Haskell / Go interfaces interface ActiveModel::Compliance def :to_key def :persisted?

    end def form_for(object : ActiveModel::Compliance) # ... end sexta-feira, 2 de março de 12
  93. ... we had partial application? sexta-feira, 2 de março de

    12
  94. _ has special semantics in many functional sexta-feira, 2 de

    março de 12
  95. _ = 1 _ # => nil sexta-feira, 2 de

    março de 12
  96. x, [y1,*_], *z = [1,[2,3,4],5] sexta-feira, 2 de março de

    12
  97. Instead of: names.each { |x| puts(x) } sexta-feira, 2 de

    março de 12
  98. Instead of: names.each { |x| puts(x) } Do: names.each &puts(_)

    sexta-feira, 2 de março de 12
  99. puts(_) #=> lambda { |x| puts(x) } respond_to?(_, _) #=>

    lambda { |x,y| respond_to?(x,y) } sexta-feira, 2 de março de 12
  100. ... we defined a syntax tree? sexta-feira, 2 de março

    de 12
  101. [:method,:bar,[ [:assign, "foo", [:integer,1]], [:var,"foo"] ]] sexta-feira, 2 de março

    de 12
  102. class Foo memoize def bar # Something end end sexta-feira,

    2 de março de 12
  103. class Foo memoize(def bar # Something end) end sexta-feira, 2

    de março de 12
  104. def memoize(method) tree = method.tree # Do something method.redefine! new_tree

    end sexta-feira, 2 de março de 12
  105. Wrapping up sexta-feira, 2 de março de 12

  106. <3 Elixir <3 github.com/josevalim/ sexta-feira, 2 de março de 12

  107. createyourproglang.com sexta-feira, 2 de março de 12

  108. José Valim @josevalim blog.plataformatec.com Questions? sexta-feira, 2 de março de

    12
  109. blog twitter ID José Valim @josevalim blog.plataformatec.com Questions? sexta-feira, 2

    de março de 12