Writing your own programming language to understand Ruby better - Euruko 2011

11,688 views
11,345 views

Published on

José Valim describes what he learned when working on Elixir and how you can understand Ruby better by writing your own programming language.

Published in: Technology
0 Comments
18 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
11,688
On SlideShare
0
From Embeds
0
Number of Embeds
1,776
Actions
Shares
0
Downloads
48
Comments
0
Likes
18
Embeds 0
No embeds

No notes for slide
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • And that was it. There are other small things I found interesting, like implementing super in Elixir, but we can discuss later if you are interested because now it is time to move to the second part of the talk. “What if?”\n\nSome of the “What if?” cases here are very unlikely to be added to Ruby because it would generate incompatibilities, but some could be there someday and some are even under discussion for Ruby 2.0.\n
  • \n
  • First off, I love Ruby blocks. But I am going to give you an alternative and explain why it maybe could be better. The point is to start a discussion and see if you think I am completely insane or not.\n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • Maybe this can cause conflict with ternaries, but I am not sure.\n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • And, in the same way, you mentioned at the time that Larry Wall (the guy how created Perl) was your hero, I can safely say your mine.\n
  • Several things I discussed here already exists in Elixir. There are a bunch other differences, like immutability and the Erlang VM is quite awesome. Come, try it and you will learn a lot.\n
  • Also, keep an eye on Rubinius VM.\n
  • \n
  • \n
  • \n
  • Writing your own programming language to understand Ruby better - Euruko 2011

    1. 1. Writing your own Programming Language to Understand Ruby betterJosé Valim blog.plataformatec.com @josevalim
    2. 2. Writing your own Programming Language to Understand Ruby better ID blog twitterJosé Valim blog.plataformatec.com @josevalim
    3. 3. I am José Valim @josevalim
    4. 4. I work at blog.plataformatec.com.br
    5. 5. Core Team Member
    6. 6. Elixir Simple Object Orientation andcharming syntax on top of Erlang VM
    7. 7. Erlang VM+Concurrent Processes+Message Based+Hot Code Swapping
    8. 8. Erlang Language+Small and quick to learn+Functional programming- Syntax gets too much in your way- No object orientation
    9. 9. Elixir Simple Object Orientation andcharming syntax on top of Erlang VM
    10. 10. <3 Ruby <3
    11. 11. 1.Things I learned about Ruby2.What if?3.Wrapping up
    12. 12. Things I learned about Ruby
    13. 13. The Syntax
    14. 14. puts “hi”
    15. 15. puts “hi” Lexer
    16. 16. puts “hi” Lexer [:identi er, “puts”], [:string, “hi”]
    17. 17. puts “hi” Lexer [:identi er, “puts”], [:string, “hi”] Parser
    18. 18. puts “hi” Lexer [:identi er, “puts”], [:string, “hi”] Parser[:call, “puts”,[ [:string, “hi”]]]
    19. 19. puts “hi” Lexer [:identi er, “puts”], [:string, “hi”] Parser[:call, “puts”,[ [:string, “hi”]]] Extra steps
    20. 20. puts “hi” Lexer [:identi er, “puts”], [:string, “hi”] Parser[:call, “puts”,[ [:string, “hi”]]] Extra steps [:call, “puts”,[ [:string, “hi”] ]]
    21. 21. puts “hi” Lexer [:identi er, “puts”], [:string, “hi”] Parser[:call, “puts”,[ [:string, “hi”]]] Extra steps [:call, “puts”,[ [:string, “hi”] ]] Interpreter/Compiler
    22. 22. puts “hi” Lexer [:identi er, “puts”], [:string, “hi”] Parser[:call, “puts”,[ [:string, “hi”]]] Extra steps [:call, “puts”,[ [:string, “hi”] ]] Interpreter/Compiler
    23. 23. Flexible Grammar
    24. 24. def foo 1endfoo #=> 1self.foo #=> 1
    25. 25. def foo 1endfoo #=> 1self.foo #=> 1foo = 2foo #=> 2self.foo #=> 1
    26. 26. foo
    27. 27. foo Lexer
    28. 28. foo Lexer [:identi er, “foo”]
    29. 29. foo Lexer [:identi er, “foo”] Parser
    30. 30. foo Lexer [:identi er, “foo”] Parser[:identi er, “foo”]
    31. 31. foo Lexer [:identi er, “foo”] Parser[:identi er, “foo”] Extra steps
    32. 32. foo Lexer [:identi er, “foo”] Parser[:identi er, “foo”] Extra steps ?
    33. 33. foo Lexer [:identi er, “foo”] Parser[:identi er, “foo”] Extra steps ? Interpreter/Compiler
    34. 34. def bar foo = 1 fooend
    35. 35. def bar foo = 1 lexer + parser fooend [:method,:bar,[ [:assign, "foo", [:integer,1]], [:identifier,"foo"] ]]
    36. 36. def bar foo = 1 lexer + parser fooend [:method,:bar,[ [:assign, "foo", [:integer,1]], [:identifier,"foo"] ]] extra steps [:method,:bar,[ [:assign, "foo", [:integer,1]], [:var,"foo"] ]]
    37. 37. def bar(arg) arg.classendbar /foo/m
    38. 38. def bar(arg) arg.classendbar /foo/mbar, foo, m = 0, 1, 2bar /foo/m
    39. 39. 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 "/" endend
    40. 40. def show @user = User.find(params[:id]) if @user.name =~ /^Ph.D/i render :action => "show" else flash[:notice] = "Ph.D required" redirect_to "/" endend
    41. 41. The Object Model
    42. 42. object = Object.newdef object.greet(name) puts "Hello #{name}"endobject.greet("Matz")
    43. 43. Ruby methods are stored in modules
    44. 44. module Greeter def greet(name) "Hello #{name}" endendclass Person include GreeterendPerson.new.greet "Matz"
    45. 45. class Person def greet(name) "Hello #{name}" endendPerson.new.greet "Matz"
    46. 46. Person.is_a?(Module) #=> trueClass.superclass #=> Module
    47. 47. object = Object.newdef object.greet(name) puts "Hello #{name}"endobject.greet("Matz")
    48. 48. object.class.ancestors#=> [Object, Kernel, BasicObject]
    49. 49. object.class.ancestors#=> [Object, Kernel, BasicObject]object.class.ancestors.any? do |r| r.method_defined?(:greet)end#=> false
    50. 50. object.class.ancestors#=> [Object, Kernel, BasicObject]object.class.ancestors.any? do |r| r.method_defined?(:greet)end#=> falseobject.singleton_class. method_defined?(:greet)#=> true
    51. 51. object.class.ancestors#=> [Object, Kernel, BasicObject]object.class.ancestors.any? do |r| r.method_defined?(:greet)end#=> falseobject.singleton_class. method_defined?(:greet)#=> trueobject.singleton_class.is_a?(Module)#=> true
    52. 52. What if?
    53. 53. ... we did not have blocks?
    54. 54. <3 Blocks <3
    55. 55. File.open("euruko.txt") do |f| f.write "doing it live"end
    56. 56. File.open "euruko.txt", do |f| f.write "doing it live"end
    57. 57. File.open "euruko.txt", do |f| f.write "doing it live"end
    58. 58. File.open("euruko.txt", do |f| f.write "doing it live"end)
    59. 59. do_it = do |f| f.write "doing it live"endFile.open "euruko.txt", do_it
    60. 60. No blocks+No need for yield, &block+Passing more than one block around is more natural
    61. 61. ... we had Array and Hash comprehensions?
    62. 62. n = [1,2,3,4][x * 2 for x in n]# => [2,4,6,8]
    63. 63. n = [1,2,3][x * 2 for x in n, x.odd?]# => [2,6]
    64. 64. n = [1,2,3,4][[x,y] for x in n, y in n, x * x == y]# => [[1,1],[2,4]]
    65. 65. n = [1,2,3,4]{x => y for x in n, y in n, x * x == y}# => { 1 => 1, 2 => 4 }
    66. 66. ... our hashes were more like JSON?
    67. 67. { a: 1 }
    68. 68. { "a": 1 }
    69. 69. ... we had pattern matching?
    70. 70. x, y, *z = [1,2,3,4,5]x #=> 1y #=> 2z #=> [3,4,5]
    71. 71. x, [y1,*y2], *z = [1,[2,3,4],5]x #=> 1y1 #=> 2y2 #=> [3,4]z #=> [5]
    72. 72. x, x, *z = [1,2,3,4,5]#=> Raises an error
    73. 73. x, x, *z = [1,1,3,4,5]#=> Works!
    74. 74. x = 1~x, *y = [3, 2, 1]#=> Raises an error!~x, *y = [1, 2, 3]# => Works!
    75. 75. ... we de ned a syntax tree?
    76. 76. [:method,:bar,[ [:assign, "foo", [:integer,1]], [:var,"foo"]]]
    77. 77. class Foo memoize def bar # Something endend
    78. 78. class Foo memoize(def bar # Something end)end
    79. 79. def memoize(method) tree = method.tree # Do something method.redefine! new_treeend
    80. 80. Wrapping up
    81. 81. <3 Matz <3
    82. 82. <3 Elixir <3github.com/josevalim/elixir
    83. 83. createyourproglang.com
    84. 84. ?José Valim blog.plataformatec.com @josevalim
    85. 85. ? ID blog twitterJosé Valim blog.plataformatec.com @josevalim

    ×