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

RubyのProcのあれをこうしました

kunou
March 14, 2017

 RubyのProcのあれをこうしました

kunou

March 14, 2017
Tweet

More Decks by kunou

Other Decks in Technology

Transcript

  1. RubyͷProcͷ͋ΕΛ͜͏͠·ͨ͠ mycallメソッドをProcクラスに生やす class Proc
 def mycall(x, y) call end
 end

    -> { _1 + _2 }.mycall(1, 2) NameError: undefined local variable or method `_1' for main:Object
  2. RubyͷProcͷ͋ΕΛ͜͏͠·ͨ͠ mycallメソッドをProcクラスに生やす class Proc
 def mycall(x, y) call end
 end

    -> { _1 + _2 }.mycall(1, 2) NameError: undefined local variable or method `_1' for main:Object ͜͜·ͰདྷΕ͹ग़དྷͨ΋ಉવͰ͢Ͷ
  3. RubyͷProcͷ͋ΕΛ͜͏͠·ͨ͠ 実行時のローカル変数として定義する class Proc
 def mycall(x, y) _1, _2 =

    x, y call end
 end -> { _1 + _2 }.mycall(1, 2) NameError: undefined local variable or method `_1' for main:Object
  4. RubyͷProcͷ͋ΕΛ͜͏͠·ͨ͠ 実行時のローカル変数として定義する class Proc
 def mycall(x, y) _1, _2 =

    x, y call end
 end -> { _1 + _2 }.mycall(1, 2) NameError: undefined local variable or method `_1' for main:Object ͓΍…ʁ
  5. RubyͷProcͷ͋ΕΛ͜͏͠·ͨ͠ 実行時のローカル変数として定義する class Proc
 def mycall(x, y) _1, _2 =

    x, y call end
 end -> { _1 + _2 }.mycall(1, 2) NameError: undefined local variable or method `_1' for main:Object Proc͕࣮ߦ͞ΕΔ࣌ͷίϯςΩετͷ ϩʔΧϧม਺͸Procͷத͔ΒݟΕͳ͍
  6. RubyͷProcͷ͋ΕΛ͜͏͠·ͨ͠ Procオブジェクトに特異メソッドを生やす class Proc
 def mycall(x, y) define_singleton_method(:_1) { x

    }
 define_singleton_method(:_2) { y } call end
 end -> { _1 + _2 }.mycall(1, 2) ಈ͘ͱࢥ͍·ͨ͠ʁ
  7. RubyͷProcͷ͋ΕΛ͜͏͠·ͨ͠ Procオブジェクトに特異メソッドを生やす class Proc
 def mycall(x, y) define_singleton_method(:_1) { x

    }
 define_singleton_method(:_2) { y } call end
 end -> { _1 + _2 }.mycall(1, 2) NameError: undefined local variable or method `_1' for main:Object
  8. RubyͷProcͷ͋ΕΛ͜͏͠·ͨ͠ Procオブジェクトに特異メソッドを生やす class Proc
 def mycall(x, y) define_singleton_method(:_1) { x

    }
 define_singleton_method(:_2) { y } call end
 end -> { _1 + _2 }.mycall(1, 2) NameError: undefined local variable or method `_1' for main:Object Procオブジェクトに特異メソッドを生やしたところで
 Procの中の処理から見られるわけではない
  9. RubyͷProcͷ͋ΕΛ͜͏͠·ͨ͠ これは… class ProcGenerator
 def generate(x, y)
 _1, _2 =

    x, y
 -> { _1 + _2 }
 end
 end proc = ProcGenerator.generate(1, 2)
 proc.call
  10. RubyͷProcͷ͋ΕΛ͜͏͠·ͨ͠ これは…行ける class ProcGenerator
 def generate(x, y)
 _1, _2 =

    x, y
 -> { _1 + _2 }
 end
 end proc = ProcGenerator.generate(1, 2)
 proc.call
 
 =>3
  11. RubyͷProcͷ͋ΕΛ͜͏͠·ͨ͠ これは…行ける class ProcGenerator
 def generate(x, y)
 _1, _2 =

    x, y
 -> { _1 + _2 }
 end
 end proc = ProcGenerator.generate(1, 2)
 proc.call
 
 =>3 なぜならば、RubyのProcは関数が宣言された時の コンテキストの状態を保持しているため(Closure)
  12. RubyͷProcͷ͋ΕΛ͜͏͠·ͨ͠ これは…行ける class ProcGenerator
 def generate(x, y)
 _1, _2 =

    x, y
 -> { _1 + _2 }
 end
 end proc = ProcGenerator.generate(1, 2)
 proc.call
 
 =>3 なぜならば、RubyのProcは関数が宣言された時の コンテキストの状態を保持しているため(Closure) ここで宣言されているものは Procの処理の中から参照・操作可能
  13. RubyͷProcͷ͋ΕΛ͜͏͠·ͨ͠ これも行ける class ProcGenerator
 def generate(x, y)
 define_singleton_method(:_1) { x

    }
 define_singleton_method(:_2) { y }
 -> { _1 + _2 }
 end
 end proc = ProcGenerator.generate(1, 2)
 proc.call
 
 =>3
  14. RubyͷProcͷ͋ΕΛ͜͏͠·ͨ͠ これも行ける class ProcGenerator def _1; 1; end
 def _2;

    2; end 
 def generate(x, y)
 -> { _1 + _2 }
 end
 end Proc宣言時にはこうなっている (イメージ)
  15. RubyͷProcͷ͋ΕΛ͜͏͠·ͨ͠ Proc#binding class ProcGenerator
 def generate(x, y)
 define_singleton_method(:_1) { x

    }
 define_singleton_method(:_2) { y }
 -> { _1 + _2 }
 end
 end proc = ProcGenerator.new.generate(1, 2) proc.binding.receiver.class

  16. RubyͷProcͷ͋ΕΛ͜͏͠·ͨ͠ Proc#binding class ProcGenerator
 def generate(x, y)
 define_singleton_method(:_1) { x

    }
 define_singleton_method(:_2) { y }
 -> { _1 + _2 }
 end
 end proc = ProcGenerator.new.generate(1, 2) proc.binding.receiver.class => ProcGenerator

  17. RubyͷProcͷ͋ΕΛ͜͏͠·ͨ͠ Proc#binding class ProcGenerator
 def generate(x, y)
 define_singleton_method(:_1) { x

    }
 define_singleton_method(:_2) { y }
 -> { _1 + _2 }
 end
 end proc = ProcGenerator.new.generate(1, 2) proc.binding.receiver.class => ProcGenerator
 Proc宣言時のレシーバーが取れている ことが分かる
  18. RubyͷProcͷ͋ΕΛ͜͏͠·ͨ͠ こうする class Proc
 def mycall(x, y) binding.receiver. instance_eval("define_singleton_method '_1',

    -> { #{x} }")
 binding.receiver. instance_eval("define_singleton_method '_2', -> { #{y} }") call end
 end
  19. RubyͷProcͷ͋ΕΛ͜͏͠·ͨ͠ 実行すると… class Proc
 def mycall(x, y) binding.receiver. instance_eval("define_singleton_method '_1',

    -> { #{x} }")
 binding.receiver. instance_eval("define_singleton_method '_2', -> { #{y} }") call end
 end -> { _1 + _2 }.mycall(1, 2) -> { _1 - _2 }.mycall(100, 20)
  20. RubyͷProcͷ͋ΕΛ͜͏͠·ͨ͠ class Proc
 def mycall(x, y) binding.receiver. instance_eval("define_singleton_method '_1', ->

    { #{x} }")
 binding.receiver. instance_eval("define_singleton_method '_2', -> { #{y} }") call end
 end -> { _1 + _2 }.mycall(1, 2) => 3 -> { _1 - _2 }.mycall(100, 20) => 80