Slide 1

Slide 1 text

Dissecting a Ruby Block Pat Shaughnessy http://patshaughnessy.net BostonRB Sept. 11, 2012

Slide 2

Slide 2 text

Why learn Ruby internals?

Slide 3

Slide 3 text

10.times do |n| puts n end

Slide 4

Slide 4 text

No content

Slide 5

Slide 5 text

Blocks: Closures in Ruby Closures and Metaprogramming

Slide 6

Slide 6 text

rb_block_t ??

Slide 7

Slide 7 text

Calling a block

Slide 8

Slide 8 text

10.times do str = "The quick brown fox..." puts str end

Slide 9

Slide 9 text

rb_block_t iseq putstring "The quick brown fox… " setdynamic str, 0 putself getdynamic str, 0 send :puts, 1 leave

Slide 10

Slide 10 text

Referencing variables from the parent scope

Slide 11

Slide 11 text

str = "The quick brown fox" 10.times do str2 = "jumps over the lazy dog." puts "#{str} #{str2}" end

Slide 12

Slide 12 text

str = "The quick brown fox"

Slide 13

Slide 13 text

YARV internal stack locals: str rb_control_frame_t LFP

Slide 14

Slide 14 text

str = "The quick brown fox" 10.times do ...

Slide 15

Slide 15 text

YARV internal stack locals: str rb_block_t iseq DFP rb_control_frame_t LFP

Slide 16

Slide 16 text

... do str2 = "jumps over the lazy dog." puts "#{str} #{str2}" end

Slide 17

Slide 17 text

rb_block_t iseq DFP YARV internal stack locals: str locals: str2 DFP rb_control_frame_t

Slide 18

Slide 18 text

rb_block_t iseq DFP putstring "jumps over the lazy dog." setdynamic str, 0 putself getdynamic str2, 1 tostring putstring " " getdynamic str, 0 tostring concatstrings 3 send :puts, 1, nil, 8, leave YARV internal stack locals: str

Slide 19

Slide 19 text

No content

Slide 20

Slide 20 text

“In computer science, a closure (also lexical closure or function closure) is a function or reference to a function together with a referencing environment...” Sussman and Steele. Scheme: An interpreter for extended lambda calculus

Slide 21

Slide 21 text

Creating and calling a lambda

Slide 22

Slide 22 text

No content

Slide 23

Slide 23 text

def display_message str = "The quick brown fox" lambda do str2 = "jumps over the lazy dog" puts "#{str} #{str2}" end end display_message.call

Slide 24

Slide 24 text

def display_message str = "The quick brown fox" ... end

Slide 25

Slide 25 text

YARV internal stack locals: str rb_control_frame_t LFP

Slide 26

Slide 26 text

str = "The quick brown fox" lambda do ... end

Slide 27

Slide 27 text

str rb_control_frame_t LFP rb_env_t env rb_proc_t rb_block_t iseq DFP envval is_lambda Stack Heap str

Slide 28

Slide 28 text

display_message.call

Slide 29

Slide 29 text

locals: str2 DFP rb_control_frame_t rb_env_t env rb_proc_t rb_block_t iseq DFP envval is_lambda Stack Heap str

Slide 30

Slide 30 text

def display_message str = "The quick brown fox" lambda do str2 = "jumps over the lazy dog" puts "#{str} #{str2}" end end display_message.call

Slide 31

Slide 31 text

Blocks: Closures in Ruby Closures and Metaprogramming

Slide 32

Slide 32 text

Using a closure to define a method

Slide 33

Slide 33 text

class Quote def initialize @str = "The quick brown fox..." end def display_message puts @str end end

Slide 34

Slide 34 text

class Quote def initialize @str = "The quick brown fox..." end define_method :display_message do puts @str end end

Slide 35

Slide 35 text

class Quote def initialize @str = "The quick brown fox" end end str2 = "jumps over the lazy dog." Quote.send(:define_method, :display_message) do puts "#{@str} #{str2}" end

Slide 36

Slide 36 text

eval and binding

Slide 37

Slide 37 text

str = "puts" str += " 2" str += " +" str += " 2" eval(str) => 4

Slide 38

Slide 38 text

class Quote def initialize @str = "The quick brown fox..." end def get_binding binding end end

Slide 39

Slide 39 text

obj = Quote.new

Slide 40

Slide 40 text

rb_control_frame_t LFP self RObject ivptr klass @str etc...

Slide 41

Slide 41 text

obj = Quote.new eval('puts @str', obj.get_binding)

Slide 42

Slide 42 text

rb_control_frame_t LFP self rb_binding_t filename line_no env rb_env_t rb_block_t iseq DFP env self Stack Heap RObject ivptr klass @str etc...

Slide 43

Slide 43 text

putstring "The quick brown fox… " setdynamic str, 0 putself getdynamic str, 0 send :puts, 1 leave YARV internal stack locals: str RObject ivptr klass rb_block_t DFP self iseq

Slide 44

Slide 44 text

instance_eval

Slide 45

Slide 45 text

class Quote def initialize @str = "The quick brown fox" end end

Slide 46

Slide 46 text

str2 = "jumps over the lazy dog." obj = Quote.new obj.instance_eval do puts "#{@str} #{str2}" end

Slide 47

Slide 47 text

instance_eval and singleton classes

Slide 48

Slide 48 text

class Quote def initialize @str = "The quick brown fox..." end end

Slide 49

Slide 49 text

obj = Quote.new obj.instance_eval do def display_message puts @str end end

Slide 50

Slide 50 text

obj.display_message The quick brown fox jumps over the lazy dog. Quote.new.display_message ...undefined method `display_message' for # (NoMethodError)

Slide 51

Slide 51 text

RClass super RClass super Object (class) Kernel (module) Quote (class) RClass super RClass super BasicObject (class) RObject klass obj (object)

Slide 52

Slide 52 text

etc... RClass super RClass super Object (class) obj (object) RObject klass SomeClass (class) RClass super #> (singleton)

Slide 53

Slide 53 text

http://patshaughnessy.net/ruby-under-a-microscope