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
Metaprogramming ruby
Search
Abhaya Thapa
October 01, 2012
Programming
200
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
450
Django cheatsheet
abhayathapa
10
600
Other Decks in Programming
See All in Programming
任せる範囲はこう広がった / How the Scope of AI Delegation Has Expanded
nrslib
0
160
Lessons from Spec-Driven Development
simas
PRO
0
220
Mujeres en SEO Summit 2026 - Greatest Disaster Hits en Web Performance
guaca
0
210
Spring Security 実践 ─ GraphQL APIで実務に役立つ 認証・認可 を学ぶ
wagyu
0
260
Signal Forms: Details & Live Coding @enterJS 2026 in Mannheim
manfredsteyer
PRO
0
200
ローカルLLMでどこまでコードが書けるか -拡張版 / How much code can be written on a local LLM Extended
kishida
12
4.5k
Oxcを導入して開発体験が向上した話
yug1224
4
340
[2026年度第1回ORセミナー] 計画最適化ベンチャーと競技プログラミング人材
terryu16
0
280
エンジニア向け会社紹介/Findy Company Profile
findyinc
6
350k
Honoでのサプライチェーン侵害対策 〜 3つのライブラリに学ぶ
yusukebe
7
1.5k
「なぜそう決めたのか」を残し続ける仕組み ― Notion AI カスタムエージェント × Slack連携による設計判断の自動記録 - NIKKEI Tech Talk #47
niftycorp
PRO
0
230
生成AI時代にこそ効くGo | Why Go Works in the Age of Generative AI
mom0tomo
8
3.3k
Featured
See All Featured
The Cult of Friendly URLs
andyhume
79
6.9k
Breaking role norms: Why Content Design is so much more than writing copy - Taylor Woolridge
uxyall
0
330
Practical Orchestrator
shlominoach
191
11k
Jess Joyce - The Pitfalls of Following Frameworks
techseoconnect
PRO
1
170
Designing for Timeless Needs
cassininazir
1
260
世界の人気アプリ100個を分析して見えたペイウォール設計の心得
akihiro_kokubo
PRO
72
40k
Marketing Yourself as an Engineer | Alaka | Gurzu
gurzu
0
250
Raft: Consensus for Rubyists
vanstee
141
7.6k
Design and Strategy: How to Deal with People Who Don’t "Get" Design
morganepeng
133
19k
Introduction to Domain-Driven Design and Collaborative software design
baasie
1
870
AI Search: Implications for SEO and How to Move Forward - #ShenzhenSEOConference
aleyda
1
1.3k
The Illustrated Children's Guide to Kubernetes
chrisshort
51
52k
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