Slide 1

Slide 1 text

Dissecting a Ruby Block Pat Shaughnessy http://patshaughnessy.net @pat_shaughnessy RubyConf Nov. 1, 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 DFP Stack frame for top level scope

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 DFP Stack frame for top level scope

Slide 16

Slide 16 text

YARV internal stack locals: str rb_control_frame_t Stack frame for internal Fixnum.times C code

Slide 17

Slide 17 text

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

Slide 18

Slide 18 text

rb_block_t iseq DFP YARV internal stack locals: str locals: str2 DFP rb_control_frame_t Stack frame for block code

Slide 19

Slide 19 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 20

Slide 20 text

No content

Slide 21

Slide 21 text

In order to solve this problem we introduce the notion of a closure [11, 14] which is a data structure containing a lambda expression, and an environment to be used when that lambda expression is applied to arguments. Sussman and Steele. Scheme: An interpreter for extended lambda calculus

Slide 22

Slide 22 text

Creating and calling a lambda

Slide 23

Slide 23 text

No content

Slide 24

Slide 24 text

(lambda (arg) (/ arg 2))

Slide 25

Slide 25 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 26

Slide 26 text

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

Slide 27

Slide 27 text

YARV internal stack locals: str rb_control_frame_t Stack frame for message_function

Slide 28

Slide 28 text

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

Slide 29

Slide 29 text

YARV internal stack rb_env_t env rb_proc_t rb_block_t iseq DFP envval is_lambda Stack Heap str locals: str rb_control_frame_t message_function stack frame

Slide 30

Slide 30 text

display_message.call

Slide 31

Slide 31 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 32

Slide 32 text

YARV internal stack rb_control_frame_t stack frame for Proc.call Heap Stack str2 DFP rb_env_t env rb_proc_t rb_block_t iseq DFP envval is_lambda str

Slide 33

Slide 33 text

Blocks: Closures in Ruby Closures and Metaprogramming

Slide 34

Slide 34 text

Using a closure to define a method

Slide 35

Slide 35 text

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

Slide 36

Slide 36 text

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

Slide 37

Slide 37 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 38

Slide 38 text

eval and binding

Slide 39

Slide 39 text

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

Slide 40

Slide 40 text

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

Slide 41

Slide 41 text

obj = Quote.new

Slide 42

Slide 42 text

rb_control_frame_t self DFP, LFP, SP YARV internal stack PC, etc. RObject ivptr klass @str etc...

Slide 43

Slide 43 text

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

Slide 44

Slide 44 text

rb_binding_t line_no env Stack Heap rb_control_frame_t get_binding stack frame filename rb_env_t rb_block_t iseq DFP RObject ivptr klass @str self, DFP self

Slide 45

Slide 45 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 46

Slide 46 text

No content