Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Dissecting a Ruby Block

Dissecting a Ruby Block

A deep dive into how MRI implements blocks, Ruby's implementation of closures. Also an explanation of the difference between blocks, lambdas, procs and bindings.

Pat Shaughnessy

November 01, 2012
Tweet

More Decks by Pat Shaughnessy

Other Decks in Technology

Transcript

  1. rb_block_t iseq putstring "The quick brown fox… " setdynamic str,

    0 putself getdynamic str, 0 send :puts, 1 leave
  2. str = "The quick brown fox" 10.times do str2 =

    "jumps over the lazy dog." puts "#{str} #{str2}" end
  3. rb_block_t iseq DFP YARV internal stack locals: str locals: str2

    DFP rb_control_frame_t Stack frame for block code
  4. 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, <ic:0> leave YARV internal stack locals: str
  5. 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
  6. def display_message str = "The quick brown fox" lambda do

    str2 = "jumps over the lazy dog" puts "#{str} #{str2}" end end display_message.call
  7. 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
  8. def display_message str = "The quick brown fox" lambda do

    str2 = "jumps over the lazy dog" puts "#{str} #{str2}" end end display_message.call
  9. 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
  10. class Quote def initialize @str = "The quick brown fox..."

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

    end define_method :display_message do puts @str end end
  12. 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
  13. str = "puts" str += " 2" str += "

    +" str += " 2" eval(str) => 4
  14. 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
  15. 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