Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
Metaprogramming ruby
Search
Abhaya Thapa
October 01, 2012
Programming
210
2
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Metaprogramming ruby
metaprogramming dsl ruby
Abhaya Thapa
October 01, 2012
More Decks by Abhaya Thapa
See All by Abhaya Thapa
Top 10 algorithms of 20th century
abhayathapa
2
460
Python Idealogies
abhayathapa
8
500
Jquery Cheatsheet
abhayathapa
10
470
Django cheatsheet
abhayathapa
10
600
Other Decks in Programming
See All in Programming
AIに “答え“を書かせるのを やめてみた
___akari11
0
120
KiroのSpecで「五目並べ」を作ってみる
satoshi256kbyte
1
370
C#の現在地 進化の歴史と、AI時代の.NET Everywhere
neuecc
5
5.1k
月間100万人のサービス刷新で、 技術選定をHonoに振り切った話
yutobara
8
6.4k
Embedded Swiftで作る自作USBデバイス によるiOSデバイスの自動テスト / iOSDC Japan 2026 glassfiber
glassfiber
0
340
TechTown - Creating Composable Callables in Contemporary C++
rollbear
0
110
Starting & Sustaining Code-Based E2E Testing for Non-Coding QA Teams( #jasstniigata )
teyamagu
PRO
1
980
パズルゲームの作り方 / how to make puzzle games
kaityo256
PRO
2
290
[Rails World 2026] Durable orchestration on Rails: from continuation to workflow
palkan
1
730
Kubernetes祭り #2 OP/ED
bells17
0
110
ハーネス設計入門 〜 基礎知識の整理から実務へのステップアップ 〜
kinopeee
22
22k
GemmaをJevのように使ってみる / Use Gemma like Jev
kishida
5
780
Featured
See All Featured
Building Applications with DynamoDB
mza
96
7.2k
A better future with KSS
kneath
240
18k
個人開発の失敗を避けるイケてる考え方 / tips for indie hackers
panda_program
123
22k
The agentic SEO stack - context over prompts
schlessera
0
970
Fantastic passwords and where to find them - at NoRuKo
philnash
53
4k
Rails Girls Zürich Keynote
gr2m
96
14k
SERP Conf. Vienna - Web Accessibility: Optimizing for Inclusivity and SEO
sarafernandez
2
1.6k
SEO for Brand Visibility & Recognition
aleyda
0
4.8k
The Success of Rails: Ensuring Growth for the Next 100 Years
eileencodes
47
8.4k
Ethics towards AI in product and experience design
skipperchong
2
420
Navigating Team Friction
lara
192
16k
Conquering PDFs: document understanding beyond plain text
inesmontani
PRO
4
3.2k
Transcript
Metaprogramming Ruby - What the hell's a DSL? • murphee
(Werner Schuster) • Blog @ http://jroller.com/page/murphee
Meta?
Programs that write Programs
Compiler
DSLs
Regexes, anyone?
Always good to start with quotes by...
Alan Kay
The general attitude seems to be that people should wear
square shoes, because squares are easier to design and manufacture than foot shaped shoes. ...
If the shoe industry has gone the way of the
computer industry it would now be running a $200-a- day course on how to walk, run and jump in square shoes." Alan Kay
DSLs • Internal – use host language • External –
Yacc, ANTLR, ...
Executable Spec
Let's start with... Dylan • http://www.networknightvision.com/ • Dylan • declarative
protocol spec
Ethernet spec in Dylan define protocol ethernet−frame ( header−frame )
summary ”ETH %= −> %=/%s ” , source−address , destination−address , compose ( summary , payload ) ; field destination−address : : <mac−address >; field source−address : : <mac−address >; field type−code : : <2byte−big−endian−unsigned−integer >; var iably−typed−field payload , type−function: select ( frame . type−code ) #x800 => <ipv4−frame >; #x806 => <arp−frame >; otherwise => <raw−frame >; end ; end ;
Ethernet spec in Dylan define protocol ethernet−frame ( header−frame )
summary ”ETH %= −> %=/%s ” , source−address , destination−address , compose ( summary , payload ) ; field destination−address : : <mac−address >; field source−address : : <mac−address >; field type−code : : <2byte−big−endian−unsigned−integer >; var iably−typed−field payload , type−function: select ( frame . type−code ) #x800 => <ipv4−frame >; #x806 => <arp−frame >; otherwise => <raw−frame >; end ; end ;
Ethernet spec in Dylan define protocol ethernet−frame ( header−frame )
summary ”ETH %= −> %=/%s ” , source−address , destination−address , compose ( summary , payload ) ; field destination−address : : <mac−address >; field source−address : : <mac−address >; field type−code : : <2byte−big−endian−unsigned−integer >; var iably−typed−field payload , type−function: select ( frame . type−code ) #x800 => <ipv4−frame >; #x806 => <arp−frame >; otherwise => <raw−frame >; end ; end ;
Design Process
Incremental does it • Sketching • Make it work •
? • Profit!
Example time • http://www.infoq.com/articles/propertiesmetaprogramming
Properties in Ruby/1 • C#-like Properties in Ruby • Why?
– to piss of Java zealots
Properties in Ruby/2 - Sketching class Foo property name end
Properties in Ruby/2 - Sketching class Foo property name end
NameError: undefined local variable or method `name' for main:Object
Properties in Ruby/3 - Fix class Foo property :name end
Properties in Ruby/3 - Fix class Foo property :name end
NameError: undefined method `property' for main:Object
Properties in Ruby/3 - Fix def property(sym) ... end class
Foo property :name end
Properties in Ruby/3 - Fix def property(sym) define_method("#{sym}=") do |value|
instance_variable_set("@#{sym}", value) end end class Foo property :name end
Properties in Ruby/3 - Fix def property(sym) define_method("#{sym}=") do |value|
instance_variable_set("@#{sym}", value) end end class Foo property :name end name=
Properties in Ruby/3 - Fix def property(sym) define_method("#{sym}=") do |value|
instance_variable_set("@#{sym}", value) end end class Foo property :name end @name
Properties in Ruby/4 - Expand def property(*sym, &bl) # Code:
Homework define_method("#{sym}=") do |value| # More Homework instance_variable_set("@#{sym}", value) end end class Tower property(:width, :height) {|val| val > 200} end
What we know by now • Class definitions are executed
• Symbols are nice • Blocks too
Another one
Pattern Matching
Parseweasel
Ruby ParseTree foo.hello(1)
Ruby ParseTree foo.hello(1) > [:vcall, :hello, :foo, [:args, [:lit, 1]
] ]
Ruby ParseTree foo.hello(1) > [:vcall, :hello, :foo, [:args, [:lit, 1]
] ] AST as: sexpr symbolic expression
ParseWeasel pattern [:vcall, :name_, :recv_, :args_]
ParseWeasel pattern [:vcall, :name_,:recv_, :args_] someone.something foo.bar murphee.speak
ParseWeasel pattern/2 [:vcall, :hello,:recv_, :args_]
ParseWeasel pattern/2 [:vcall, :hello,:recv_, :args_] foo.bar foo.hello huey().lewey().hello() huey().speak
ParseWeasel handlers handler([:vcall, :hello,:recv_, :args_]){|s| puts “Found a hello #{s[:recv]}”
}
ParseWeasel use case: optimizer replace([:call, :op_, :*, [:lit, 0] ]){|s|
[:lit, 0] }
ParseWeasel use case: optimizer replace([:call, :op_, :*, [:lit, 0] ]){|s|
[:lit, 0] } x = foo * 0
Ruby DSLs • Keep it simple • Stick to basics
• If it limps like a hack – it probably is one
Let's push it further
Let's mess up the syntax
Hello LISP (defun factorial (x) (if (zerop x) 1 (*
x (factorial ( x 1))) ) ) (factorial 42)
Macros
C Preprocessor
C Preprocessor
LISP Macro example: Infix (* a 42)
I want my infix!
LISP Macro example: Infix (infix (a * 42) ) what
I write
LISP Macro example: Infix (defmacro infix (one op two &rest
body) `(,op ,one ,two ) ) (infix (a * 42) ) what I write
LISP Macro example: Infix (defmacro infix (one op two &rest
body) `(,op ,one ,two ) ) (infix (a * 42) ) (* a 42) what I write what gets executed
LISP Macro: real use cases • Practical Lisp – MP3
binary parser – executable spec • Many LISP control structures
Macros in the real world • Mathematica – D[x ^
2] – Integrate[x ^ 3] – Expand[ x ^ 42] – • Macro-like • “FullForm” ~ s-expr – 3x -> Times[3, x ]
Let's wrap up • Practical Lisp – http://www.gigamonkeys.com/book/ • http://ola-bini.blogspot.com/2006/09/ruby-metaprogramming-techniques.html
• http://www.infoq.com/articles/properties-metaprogramming