Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Writing your own Programming Language to Unders...
Search
gogaruco
September 27, 2011
3
87
Writing your own Programming Language to Understand Ruby better
by Jose Valim
gogaruco
September 27, 2011
Tweet
Share
More Decks by gogaruco
See All by gogaruco
Wesley Beary at GoGaRuCo 2011
gogaruco
2
55
CouchDB & Ruby - You're doing it wrong
gogaruco
5
290
Ruby Javascript and the Mobile Web
gogaruco
1
75
KidsRuby: Think of the Children
gogaruco
1
140
Smalltalk on Rubinius
gogaruco
1
59
Go for the Rubyist
gogaruco
3
250
Fast Rails Tests
gogaruco
1
160
Featured
See All Featured
The Myth of the Modular Monolith - Day 2 Keynote - Rails World 2024
eileencodes
16
2.1k
Fashionably flexible responsive web design (full day workshop)
malarkey
405
65k
Thoughts on Productivity
jonyablonski
67
4.3k
Music & Morning Musume
bryan
46
6.2k
Bash Introduction
62gerente
608
210k
Fight the Zombie Pattern Library - RWD Summit 2016
marcelosomers
232
17k
A better future with KSS
kneath
238
17k
Design and Strategy: How to Deal with People Who Don’t "Get" Design
morganepeng
126
18k
個人開発の失敗を避けるイケてる考え方 / tips for indie hackers
panda_program
93
16k
Happy Clients
brianwarren
98
6.7k
Typedesign – Prime Four
hannesfritz
40
2.4k
Cheating the UX When There Is Nothing More to Optimize - PixelPioneers
stephaniewalter
280
13k
Transcript
José Valim @josevalim blog.plataformatec.com Writing your own Programming Language to
Understand Ruby better Friday, September 16, 2011
blog twitter ID José Valim @josevalim blog.plataformatec.com Writing your own
Programming Language to Understand Ruby better Friday, September 16, 2011
Elixir Simple Object Orientation and charming syntax on top of
Erlang VM Friday, September 16, 2011
Erlang VM + Concurrent Processes + Message Based + Hot
Code Swapping + Runs with low memory Friday, September 16, 2011
Erlang Language + Small and quick to learn + Functional
programming - Syntax gets too much in your way - No object orientation Friday, September 16, 2011
Elixir Simple Object Orientation and charming syntax on top of
Erlang VM Friday, September 16, 2011
<3 Ruby <3 Friday, September 16, 2011
Friday, September 16, 2011
@tenderl—ve Friday, September 16, 2011
* Things I learned about Ruby * What if? Friday,
September 16, 2011
Things I learned about Ruby Friday, September 16, 2011
The Syntax Friday, September 16, 2011
puts “hi” Friday, September 16, 2011
puts “hi” Lexer Friday, September 16, 2011
puts “hi” Lexer [:identifier, “puts”], [:string, “hi”] Friday, September 16,
2011
puts “hi” Lexer [:identifier, “puts”], [:string, “hi”] Parser Friday, September
16, 2011
puts “hi” Lexer [:identifier, “puts”], [:string, “hi”] [:call, “puts”,[ [:string,
“hi”] ]] Parser Friday, September 16, 2011
puts “hi” Lexer [:identifier, “puts”], [:string, “hi”] [:call, “puts”,[ [:string,
“hi”] ]] Parser Semantic Analysis Friday, September 16, 2011
puts “hi” Lexer [:identifier, “puts”], [:string, “hi”] [:call, “puts”,[ [:string,
“hi”] ]] Parser Semantic Analysis [:call, “puts”,[ [:string, “hi”] ]] Friday, September 16, 2011
puts “hi” Lexer [:identifier, “puts”], [:string, “hi”] [:call, “puts”,[ [:string,
“hi”] ]] Parser Semantic Analysis [:call, “puts”,[ [:string, “hi”] ]] Native / Bytecode Friday, September 16, 2011
puts “hi” Lexer [:identifier, “puts”], [:string, “hi”] [:call, “puts”,[ [:string,
“hi”] ]] Parser Semantic Analysis [:call, “puts”,[ [:string, “hi”] ]] Native / Bytecode Friday, September 16, 2011
Flexible Grammar Friday, September 16, 2011
def foo 1 end foo #=> 1 self.foo #=> 1
Friday, September 16, 2011
def foo 1 end foo #=> 1 self.foo #=> 1
foo = 2 foo #=> 2 self.foo #=> 1 Friday, September 16, 2011
foo Friday, September 16, 2011
foo Lexer Friday, September 16, 2011
foo Lexer [:identifier, “foo”] Friday, September 16, 2011
foo Lexer [:identifier, “foo”] Parser Friday, September 16, 2011
foo Lexer [:identifier, “foo”] [:identifier, “foo”] Parser Friday, September 16,
2011
foo Lexer [:identifier, “foo”] [:identifier, “foo”] Parser Semantic Analysis Friday,
September 16, 2011
foo Lexer [:identifier, “foo”] [:identifier, “foo”] Parser Semantic Analysis ?
Friday, September 16, 2011
foo Lexer [:identifier, “foo”] [:identifier, “foo”] Parser Semantic Analysis Native
/ Bytecode ? Friday, September 16, 2011
def bar foo = 1 foo end Friday, September 16,
2011
def bar foo = 1 foo end [:method,:bar,[ [:assign, "foo",
[:integer,1]], [:identifier,"foo"] ]] lexer + parser Friday, September 16, 2011
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
Friday, September 16, 2011
def bar(arg) arg.class end bar /foo/m Friday, September 16, 2011
def bar(arg) arg.class end bar /foo/m bar, foo, m =
0, 1, 2 bar /foo/m Friday, September 16, 2011
Friday, September 16, 2011
Friday, September 16, 2011
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
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
Trivia Friday, September 16, 2011
Trivia array = [1,2,3] Friday, September 16, 2011
Trivia array = [1,2,3] array.length+1 Friday, September 16, 2011
Trivia array = [1,2,3] array.length+1 #=> 4 Friday, September 16,
2011
Trivia array = [1,2,3] array.length+1 #=> 4 array.length +1 Friday,
September 16, 2011
Trivia array = [1,2,3] array.length+1 #=> 4 array.length +1 #=>
ArgumentError Friday, September 16, 2011
Trivia array = [1,2,3] array.length+1 #=> 4 array.length +1 #=>
ArgumentError array.length + 1 Friday, September 16, 2011
Trivia array = [1,2,3] array.length+1 #=> 4 array.length +1 #=>
ArgumentError array.length + 1 #=> 4 Friday, September 16, 2011
Trivia p { } p { a: 1 } Is
it a block or a hash? Friday, September 16, 2011
The Object Model Friday, September 16, 2011
object = Object.new def object.greet(name) puts "Hello #{name}" end object.greet("Matz")
Friday, September 16, 2011
Ruby methods are stored in modules Friday, September 16, 2011
module Greeter def greet(name) "Hello #{name}" end end class Person
include Greeter end Person.new.greet "Matz" Friday, September 16, 2011
class Person def greet(name) "Hello #{name}" end end Person.new.greet "Matz"
Friday, September 16, 2011
Person.is_a?(Module) #=> true Class.superclass #=> Module Friday, September 16, 2011
object = Object.new def object.greet(name) puts "Hello #{name}" end object.greet("Matz")
Friday, September 16, 2011
object.class.ancestors #=> [Object, Kernel, BasicObject] Friday, September 16, 2011
object.class.ancestors #=> [Object, Kernel, BasicObject] object.class.ancestors.any? do |r| r.method_defined?(:greet) end
#=> false Friday, September 16, 2011
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
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
_why once said: Creating your own programming language is fun
if you can keep it under 10k LOC Trivia Friday, September 16, 2011
Ruby’s parse.y is more than 10k LOC Trivia Friday, September
16, 2011
What if? Friday, September 16, 2011
... we did not have blocks? Friday, September 16, 2011
<3 Blocks <3 Friday, September 16, 2011
File.open "gogaruco.txt" do |f| f.write "doing it live" end Friday,
September 16, 2011
File.open "gogaruco.txt", do |f| f.write "doing it live" end Friday,
September 16, 2011
File.open "gogaruco.txt", do |f| f.write "doing it live" end Friday,
September 16, 2011
File.open("gogaruco.txt", do |f| f.write "doing it live" end) Friday, September
16, 2011
do_it = do |f| f.write "doing it live" end File.open
"gogaruco.txt", do_it Friday, September 16, 2011
No blocks + No need for yield, &block + Passing
more than one block around is more natural Friday, September 16, 2011
... we had Array and Hash comprehensions? Friday, September 16,
2011
n = [1,2,3,4] [x * 2 for x in n]
# => [2,4,6,8] Friday, September 16, 2011
n = [1,2,3] [x * 2 for x in n,
x.odd?] # => [2,6] Friday, September 16, 2011
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
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
... our hashes were more like JSON? Friday, September 16,
2011
{ a: 1 } Friday, September 16, 2011
{ "a": 1 } Friday, September 16, 2011
Trivia { "a-b": 1 } == { :"a-b" => 1
} Friday, September 16, 2011
... we had (better) pattern matching? Friday, September 16, 2011
x, y, *z = [1,2,3,4,5] x #=> 1 y #=>
2 z #=> [3,4,5] Friday, September 16, 2011
x, [y1,*y2], *z = [1,[2,3,4],5] x #=> 1 y1 #=>
2 y2 #=> [3,4] z #=> [5] Friday, September 16, 2011
x, x, *z = [1,2,3,4,5] #=> Raises an error Friday,
September 16, 2011
x, x, *z = [1,1,3,4,5] #=> Works! Friday, September 16,
2011
x = 1 ^x, *y = [3, 2, 1] #=>
Raises an error! ^x, *y = [1, 2, 3] # => Works! Friday, September 16, 2011
def form_for(object) case object when Hash # ... when Array
# ... else # ... end end Friday, September 16, 2011
def form_for(record : Hash) # ... end def form_for(record :
Array) # ... end def form_for(record) # ... end Friday, September 16, 2011
+ Better to maintain + Better to document - No
duck typing Method pattern matching Friday, September 16, 2011
Haskell / Go interfaces interface ActiveModel::Compliance def :to_key def :persisted?
end def form_for(object : ActiveModel::Compliance) # ... end Friday, September 16, 2011
... we had partial application? Friday, September 16, 2011
_ has special semantics in many functional programming languages Friday,
September 16, 2011
_ = 1 _ # => nil Friday, September 16,
2011
x, [y1,*_], *z = [1,[2,3,4],5] Friday, September 16, 2011
Instead of: names.each { |x| puts(x) } Friday, September 16,
2011
Instead of: names.each { |x| puts(x) } Do: names.each &puts(_)
Friday, September 16, 2011
puts(_) #=> lambda { |x| puts(x) } respond_to?(_, _) #=>
lambda { |x,y| respond_to?(x,y) } Friday, September 16, 2011
... we defined a syntax tree? Friday, September 16, 2011
[:method,:bar,[ [:assign, "foo", [:integer,1]], [:var,"foo"] ]] Friday, September 16, 2011
class Foo memoize def bar # Something end end Friday,
September 16, 2011
class Foo memoize(def bar # Something end) end Friday, September
16, 2011
def memoize(method) tree = method.tree # Do something method.redefine! new_tree
end Friday, September 16, 2011
Wrapping up Friday, September 16, 2011
<3 Elixir <3 github.com/josevalim/elixir Friday, September 16, 2011
createyourproglang.com Friday, September 16, 2011
José Valim @josevalim blog.plataformatec.com Questions? Friday, September 16, 2011
blog twitter ID José Valim @josevalim blog.plataformatec.com Questions? Friday, September
16, 2011