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

Writing your own Programming Language to Unders...

gogaruco
September 27, 2011
87

Writing your own Programming Language to Understand Ruby better

by Jose Valim

gogaruco

September 27, 2011
Tweet

Transcript

  1. blog twitter ID José Valim @josevalim blog.plataformatec.com Writing your own

    Programming Language to Understand Ruby better Friday, September 16, 2011
  2. Erlang VM + Concurrent Processes + Message Based + Hot

    Code Swapping + Runs with low memory Friday, September 16, 2011
  3. Erlang Language + Small and quick to learn + Functional

    programming - Syntax gets too much in your way - No object orientation Friday, September 16, 2011
  4. puts “hi” Lexer [:identifier, “puts”], [:string, “hi”] [:call, “puts”,[ [:string,

    “hi”] ]] Parser Semantic Analysis Friday, September 16, 2011
  5. puts “hi” Lexer [:identifier, “puts”], [:string, “hi”] [:call, “puts”,[ [:string,

    “hi”] ]] Parser Semantic Analysis [:call, “puts”,[ [:string, “hi”] ]] Friday, September 16, 2011
  6. puts “hi” Lexer [:identifier, “puts”], [:string, “hi”] [:call, “puts”,[ [:string,

    “hi”] ]] Parser Semantic Analysis [:call, “puts”,[ [:string, “hi”] ]] Native / Bytecode Friday, September 16, 2011
  7. puts “hi” Lexer [:identifier, “puts”], [:string, “hi”] [:call, “puts”,[ [:string,

    “hi”] ]] Parser Semantic Analysis [:call, “puts”,[ [:string, “hi”] ]] Native / Bytecode Friday, September 16, 2011
  8. def foo 1 end foo #=> 1 self.foo #=> 1

    Friday, September 16, 2011
  9. def foo 1 end foo #=> 1 self.foo #=> 1

    foo = 2 foo #=> 2 self.foo #=> 1 Friday, September 16, 2011
  10. def bar foo = 1 foo end [:method,:bar,[ [:assign, "foo",

    [:integer,1]], [:identifier,"foo"] ]] lexer + parser Friday, September 16, 2011
  11. 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 Friday, September 16, 2011
  12. def bar(arg) arg.class end bar /foo/m bar, foo, m =

    0, 1, 2 bar /foo/m Friday, September 16, 2011
  13. 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 Friday, September 16, 2011
  14. 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 Friday, September 16, 2011
  15. Trivia array = [1,2,3] array.length+1 #=> 4 array.length +1 #=>

    ArgumentError Friday, September 16, 2011
  16. Trivia array = [1,2,3] array.length+1 #=> 4 array.length +1 #=>

    ArgumentError array.length + 1 Friday, September 16, 2011
  17. Trivia array = [1,2,3] array.length+1 #=> 4 array.length +1 #=>

    ArgumentError array.length + 1 #=> 4 Friday, September 16, 2011
  18. Trivia p { } p { a: 1 } Is

    it a block or a hash? Friday, September 16, 2011
  19. module Greeter def greet(name) "Hello #{name}" end end class Person

    include Greeter end Person.new.greet "Matz" Friday, September 16, 2011
  20. 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 Friday, September 16, 2011
  21. 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 Friday, September 16, 2011
  22. _why once said: Creating your own programming language is fun

    if you can keep it under 10k LOC Trivia Friday, September 16, 2011
  23. do_it = do |f| f.write "doing it live" end File.open

    "gogaruco.txt", do_it Friday, September 16, 2011
  24. No blocks + No need for yield, &block + Passing

    more than one block around is more natural Friday, September 16, 2011
  25. n = [1,2,3,4] [x * 2 for x in n]

    # => [2,4,6,8] Friday, September 16, 2011
  26. n = [1,2,3] [x * 2 for x in n,

    x.odd?] # => [2,6] Friday, September 16, 2011
  27. n = [1,2,3,4] [[x,y] for x in n, y in

    n, x * x == y] # => [[1,1],[2,4]] Friday, September 16, 2011
  28. n = [1,2,3,4] {x => y for x in n,

    y in n, x * x == y} # => { 1 => 1, 2 => 4 } Friday, September 16, 2011
  29. Trivia { "a-b": 1 } == { :"a-b" => 1

    } Friday, September 16, 2011
  30. x, y, *z = [1,2,3,4,5] x #=> 1 y #=>

    2 z #=> [3,4,5] Friday, September 16, 2011
  31. x, [y1,*y2], *z = [1,[2,3,4],5] x #=> 1 y1 #=>

    2 y2 #=> [3,4] z #=> [5] Friday, September 16, 2011
  32. x = 1 ^x, *y = [3, 2, 1] #=>

    Raises an error! ^x, *y = [1, 2, 3] # => Works! Friday, September 16, 2011
  33. def form_for(object) case object when Hash # ... when Array

    # ... else # ... end end Friday, September 16, 2011
  34. def form_for(record : Hash) # ... end def form_for(record :

    Array) # ... end def form_for(record) # ... end Friday, September 16, 2011
  35. + Better to maintain + Better to document - No

    duck typing Method pattern matching Friday, September 16, 2011
  36. Haskell / Go interfaces interface ActiveModel::Compliance def :to_key def :persisted?

    end def form_for(object : ActiveModel::Compliance) # ... end Friday, September 16, 2011
  37. puts(_) #=> lambda { |x| puts(x) } respond_to?(_, _) #=>

    lambda { |x,y| respond_to?(x,y) } Friday, September 16, 2011