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
This Talk is so Meta
Search
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
Nugroho Herucahyono
September 26, 2013
Programming
130
1
Share
This Talk is so Meta
Introduction to metaprogramming in ruby
Nugroho Herucahyono
September 26, 2013
More Decks by Nugroho Herucahyono
See All by Nugroho Herucahyono
Simply Distributed
xinuc
0
120
Choosing the right technology
xinuc
0
180
A Tale of a Happy Programmer
xinuc
0
150
Rails on Wiradipa - Jakarta.rb Februari 2012 - Hafiz Badrie Lubiz
xinuc
1
170
Why Ruby? - View from business aspect - Jakarta.rb Februari 2012 - Fajrin Rasyid
xinuc
1
360
Other Decks in Programming
See All in Programming
我々はなぜ「層」を分けるのか〜「関心の分離」と「抽象化」で手に入れる変更に強いシンプルな設計〜 #phperkaigi / PHPerKaigi 2026
shogogg
2
750
Laravel Nightwatchの裏側 - Laravel公式Observabilityツールを支える設計と実装
avosalmon
1
300
CS教育のDX AIによる育成の効率化
niftycorp
PRO
0
180
Ruby and LLM Ecosystem 2nd
koic
1
1.4k
The Past, Present, and Future of Enterprise Java
ivargrimstad
0
1.3k
夢の無限スパゲッティ製造機 -実装篇- #phpstudy
o0h
PRO
0
190
AI時代の脳疲弊と向き合う ~言語学としてのPHP~
sakuraikotone
1
1.8k
Cyrius ーLinux非依存にコンテナをネイティブ実行する専用OSー
n4mlz
0
270
RSAが破られる前に知っておきたい 耐量子計算機暗号(PQC)入門 / Intro to PQC: Preparing for the Post-RSA Era
mackey0225
3
110
車輪の再発明をしよう!PHP で実装して学ぶ、Web サーバーの仕組みと HTTP の正体
h1r0
2
480
PHPで TLSのプロトコルを実装してみる
higaki_program
0
730
Reactive ❤️ Loom: A Forbidden Love Story
franz1981
2
210
Featured
See All Featured
A Modern Web Designer's Workflow
chriscoyier
698
190k
Avoiding the “Bad Training, Faster” Trap in the Age of AI
tmiket
0
110
DBのスキルで生き残る技術 - AI時代におけるテーブル設計の勘所
soudai
PRO
64
53k
A Soul's Torment
seathinner
5
2.6k
Art, The Web, and Tiny UX
lynnandtonic
304
21k
The Success of Rails: Ensuring Growth for the Next 100 Years
eileencodes
47
8k
The World Runs on Bad Software
bkeepers
PRO
72
12k
Agile that works and the tools we love
rasmusluckow
331
21k
Building a A Zero-Code AI SEO Workflow
portentint
PRO
0
420
Code Reviewing Like a Champion
maltzj
528
40k
How to Ace a Technical Interview
jacobian
281
24k
Principles of Awesome APIs and How to Build Them.
keavy
128
17k
Transcript
Jakarta.rb 25 September 2013
Xinuc (Ruby) Programmer @xinuc (github, twitter) Works at Bukalapak.com Intro
We're hiring www.bukalapak.com/career Intro
This Talk is so Meta
Metaprogramming, because F*** You, That's why!
Metaprogramming: the writing of computer programs that write or manipulate
other programs (or themselves) as their data, or that do potato potato potato... Metaprogramming
Write Program that writes program (that writes program) (that writes
program) Metaprogramming
- Meet your first Meta - attr_accessor - The basic
- block - ruby class structure - method lookup - eigenclass - The technique - define_method - method_missing - method cache - class_eval - instance_eval - eval Agenda
Meet Your first meta
class Person { private String name; public String getName() {
return this.name; } public void setName(String name) { this.name = name; } } attr_accessor
class Person attr_accessor :name end attr_accessor
class Person def name @name end def name=(name) @name =
name end end attr_accessor
The Basic Some groundwork we need to lay
block
A block is a just chunk of code that can
be called 3.times do puts “hello” end block
A block is just a special form of a proc
def show_me_the_block(&block) block end block vs proc
$ b = show_me_the_block do puts “hello” end => #<Proc:0x00000000d8d600:4>
$ b.call => Hello $ b.class => Proc block vs proc
my_proc = proc { puts “hello” } my_proc.call => hello
3.times &my_proc => hello hello hello block vs proc
A block is a closure because it can access its
environment name = “xinuc” 3.times do puts “hello #{name}” end block & closure
Ruby method lookup
Inside a ruby object klass iv_tbl flags klass iv_tbl flags
m_tbl super object class
Class structure MyClass Object Class super klass klass klass
Class structure Object BasicObject super MyClassA super MyClassB super
Class structure Object BasicObject super MyClassA super MyClassB super MyModule
mixin
eigenclass
o = Object.new o.hello => NoMethodError: undefined method `hello' def
o.hello puts “hello” end o.hello => hello eigen_class
o = Object.new eigen = o.singleton_class #1.9 eigen = class
<< o; self; end eigen_class
Class structure Object BasicObject super MyClassA super eigen_class <virtual> super
MyModule object klass mixin
The Techniques
Define method
# nested def def learn_to_shout puts “learning....” def shout puts
“Wazzzaaaap!!” end end Define method
$ shout => undefined local variable or method `shout' $
learn_to_shout => learning.... $ shout => Wazzzaaaap!! Define method
def learn_to_shout puts “learning....” def shout puts “Wazzzaaaap!!” end end
Define method
def who_are_you puts “I'm batman” def who_are_you puts “I'm superman”
def who_are_you puts “I'm ironman” end end end Define method
def who_are_you puts “I'm batman” def who_are_you puts “I'm superman”
def who_are_you puts “I'm ironman” end end end Hypocrite method
def who_are_you puts “I'm batman” def who_are_you puts “I'm superman”
def who_are_you puts “I'm ironman” end end end Yo dawg method
define_method
define_method method takes a method name and a block, then
creates a method with block as the method body define_method :name do |args| # method body end define_method method
def attr_accessor(*attrs) attrs.each do |attr| define_method attr do instance_variable_get “@#{attr}”
end define_method “#{attr}=” do |val| instance_variable_set “@#{attr}”, val end end end attr_accessor
method_missing
class Person def method_missing(name, *args, &block) puts “method #{name}” end
end p = Person.new p.omg_lol => method omg_lol method_missing
require 'builder' xml = Builder::XmlMarkup.new xml.coder do xml.name 'xinuc' xml.language
'Ruby' end method_missing
Class structure Object BasicObject super MyClass super eigen_class <virtual> super
MyModule my_object klass mixin
Lazy method definition
class Person def method_missing(name, *args, &block) self.class.class_eval do define_method(name) do
puts ”method #{defined} defined” end end self.send name, *args end end Lazy method definition
p = Person.new p.respond_to? :hello => false p.hello => method
hello defined p.respond_to? :hello => true Lazy method definition
class User < ActiveRecord::Base end User.find_by_username “xinuc” Lazy method definition
class_eval
class Person end Person.class_eval do def hello puts “hello” end
end p = Person.new p.hello class_eval
instance_eval
class Person end p = Person.new p.instance_eval do def hello
puts “hello” end end instance_eval
class Person end p = Person.new p.singleton_class.class_eval do def hello
puts “hello” end end p.hello instance_eval
instance_eval change the “self” inside a block s = “Hello”
s.instance_eval do puts self.upcase end instance_eval
# sunspot class User < ActiveRecord::Base # method text &
integer # not defined here searchable do # but we can call method text & integer here text :name integer :age end end instance_eval
Here comes the devil
Class.new Create classes dynamically
1000.times do Class.new do end end Class.new
“The evil” eval
eval <<-EOF def do_evil puts “do evil things” end EOF
do_evil eval
Warning!
Metaprogramming is a chainsaw warning
You don't slice your bread with a chainsaw! warning
Unless you're a bear with chainsaw hands warning
Thank you