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

  • 6,251 views
Uploaded on

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

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

More in: Technology
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
No Downloads

Views

Total Views
6,251
On Slideshare
0
From Embeds
0
Number of Embeds
3

Actions

Shares
Downloads
40
Comments
0
Likes
13

Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    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

Transcript

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