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
92
3
Share
Writing your own Programming Language to Understand Ruby better
by Jose Valim
gogaruco
September 27, 2011
More Decks by gogaruco
See All by gogaruco
Wesley Beary at GoGaRuCo 2011
gogaruco
2
61
CouchDB & Ruby - You're doing it wrong
gogaruco
5
300
Ruby Javascript and the Mobile Web
gogaruco
1
81
KidsRuby: Think of the Children
gogaruco
1
160
Smalltalk on Rubinius
gogaruco
1
64
Go for the Rubyist
gogaruco
3
260
Fast Rails Tests
gogaruco
1
170
Featured
See All Featured
Let's Do A Bunch of Simple Stuff to Make Websites Faster
chriscoyier
508
140k
Efficient Content Optimization with Google Search Console & Apps Script
katarinadahlin
PRO
1
480
What’s in a name? Adding method to the madness
productmarketing
PRO
24
4k
A Soul's Torment
seathinner
6
2.6k
Art, The Web, and Tiny UX
lynnandtonic
304
21k
The Power of CSS Pseudo Elements
geoffreycrofte
82
6.2k
Connecting the Dots Between Site Speed, User Experience & Your Business [WebExpo 2025]
tammyeverts
11
880
First, design no harm
axbom
PRO
2
1.2k
Save Time (by Creating Custom Rails Generators)
garrettdimon
PRO
32
2.7k
VelocityConf: Rendering Performance Case Studies
addyosmani
333
25k
30 Presentation Tips
portentint
PRO
1
270
How to Ace a Technical Interview
jacobian
281
24k
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