Slide 1

Slide 1 text

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

Slide 2

Slide 2 text

kunou ITSํ໘͔Βདྷ·ͨ͠

Slide 3

Slide 3 text

RubyͷProcͷ͋ΕΛ͜͏͠·ͨ͠ ࠓճ΍Γ͍ͨ͜ͱ Clojureで

Slide 4

Slide 4 text

RubyͷProcͷ͋ΕΛ͜͏͠·ͨ͠ ࠓճ΍Γ͍ͨ͜ͱ Clojureで ((fn [x y] (+ x y)) 1 2)

Slide 5

Slide 5 text

RubyͷProcͷ͋ΕΛ͜͏͠·ͨ͠ ࠓճ΍Γ͍ͨ͜ͱ Clojureで ((fn [x y] (+ x y)) 1 2) ࣮Ҿ਺

Slide 6

Slide 6 text

RubyͷProcͷ͋ΕΛ͜͏͠·ͨ͠ ࠓճ΍Γ͍ͨ͜ͱ Clojureで ((fn [x y] (+ x y)) 1 2) ແ໊ؔ਺

Slide 7

Slide 7 text

RubyͷProcͷ͋ΕΛ͜͏͠·ͨ͠ ࠓճ΍Γ͍ͨ͜ͱ Clojureで ((fn [x y] (+ x y)) 1 2) ԾҾ਺

Slide 8

Slide 8 text

RubyͷProcͷ͋ΕΛ͜͏͠·ͨ͠ ࠓճ΍Γ͍ͨ͜ͱ Clojureで ((fn [x y] (+ x y)) 1 2)

Slide 9

Slide 9 text

RubyͷProcͷ͋ΕΛ͜͏͠·ͨ͠ ࠓճ΍Γ͍ͨ͜ͱ Clojureで ((fn [x y] (+ x y)) 1 2) =>3

Slide 10

Slide 10 text

RubyͷProcͷ͋ΕΛ͜͏͠·ͨ͠ ࠓճ΍Γ͍ͨ͜ͱ Clojureで (#(+ %1 %2) 1 2)

Slide 11

Slide 11 text

RubyͷProcͷ͋ΕΛ͜͏͠·ͨ͠ ࠓճ΍Γ͍ͨ͜ͱ Clojureで (#(+ %1 %2) 1 2) ࣮Ҿ਺

Slide 12

Slide 12 text

RubyͷProcͷ͋ΕΛ͜͏͠·ͨ͠ ࠓճ΍Γ͍ͨ͜ͱ Clojureで (#(+ %1 %2) 1 2) ແ໊ؔ਺

Slide 13

Slide 13 text

RubyͷProcͷ͋ΕΛ͜͏͠·ͨ͠ ࠓճ΍Γ͍ͨ͜ͱ Clojureで (#(+ %1 %2) 1 2)

Slide 14

Slide 14 text

RubyͷProcͷ͋ΕΛ͜͏͠·ͨ͠ ࠓճ΍Γ͍ͨ͜ͱ Clojureで (#(+ %1 %2) 1 2) =>3

Slide 15

Slide 15 text

RubyͷProcͷ͋ΕΛ͜͏͠·ͨ͠ ࠓճ΍Γ͍ͨ͜ͱ Clojureで (#(+ %1 %2) 1 2) =>3 ԾҾ਺ͷએݴΛলུग़དྷΔ

Slide 16

Slide 16 text

RubyͷProcͷ͋ΕΛ͜͏͠·ͨ͠ ࠓճ΍Γ͍ͨ͜ͱ Clojureで (#(+ %1 %2) 1 2) =>3 ԾҾ਺ͷએݴΛলུग़དྷΔ ͜ΕΛRubyͰॻ͚ΔΑ͏ʹ͢Δʂ

Slide 17

Slide 17 text

RubyͷProcͷ͋ΕΛ͜͏͠·ͨ͠ ׬੒Πϝʔδ -> { _1 + _2 }.mycall(1, 2) => 3 ͱΓ͋͑ͣɺҾ਺ΛೋݸݻఆͰ࡞ͬͯΈΔ

Slide 18

Slide 18 text

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

Slide 19

Slide 19 text

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

Slide 20

Slide 20 text

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

Slide 21

Slide 21 text

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 ͜͜·ͰདྷΕ͹ग़དྷͨ΋ಉવͰ͢Ͷ

Slide 22

Slide 22 text

RubyͷProcͷ͋ΕΛ͜͏͠·ͨ͠ 実行時のローカル変数として定義する class Proc
 def mycall(x, y) _1, _2 = x, y call end
 end

Slide 23

Slide 23 text

RubyͷProcͷ͋ΕΛ͜͏͠·ͨ͠ 実行時のローカル変数として定義する class Proc
 def mycall(x, y) _1, _2 = x, y call end
 end ͜͜Λ଍ͨ͠

Slide 24

Slide 24 text

RubyͷProcͷ͋ΕΛ͜͏͠·ͨ͠ 実行時のローカル変数として定義する class Proc
 def mycall(x, y) _1, _2 = x, y call end
 end -> { _1 + _2 }.mycall(1, 2)

Slide 25

Slide 25 text

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

Slide 26

Slide 26 text

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 ͓΍…ʁ

Slide 27

Slide 27 text

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ͷத͔ΒݟΕͳ͍

Slide 28

Slide 28 text

RubyͷProcͷ͋ΕΛ͜͏͠·ͨ͠ 気を取り直して

Slide 29

Slide 29 text

RubyͷProcͷ͋ΕΛ͜͏͠·ͨ͠ Procオブジェクトに特異メソッドを生やす class Proc
 def mycall(x, y) define_singleton_method(:_1) { x }
 define_singleton_method(:_2) { y } call end
 end

Slide 30

Slide 30 text

RubyͷProcͷ͋ΕΛ͜͏͠·ͨ͠ Procオブジェクトに特異メソッドを生やす class Proc
 def mycall(x, y) define_singleton_method(:_1) { x }
 define_singleton_method(:_2) { y } call end
 end ͜͏Ͱ͢Ͷʂ

Slide 31

Slide 31 text

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)

Slide 32

Slide 32 text

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) ಈ͘ͱࢥ͍·ͨ͠ʁ

Slide 33

Slide 33 text

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

Slide 34

Slide 34 text

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の中の処理から見られるわけではない

Slide 35

Slide 35 text

RubyͷProcͷ͋ΕΛ͜͏͠·ͨ͠ 真面目に考えましょう

Slide 36

Slide 36 text

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

Slide 37

Slide 37 text

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

Slide 38

Slide 38 text

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)

Slide 39

Slide 39 text

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の処理の中から参照・操作可能

Slide 40

Slide 40 text

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

Slide 41

Slide 41 text

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

Slide 42

Slide 42 text

RubyͷProcͷ͋ΕΛ͜͏͠·ͨ͠ 要するに

Slide 43

Slide 43 text

RubyͷProcͷ͋ΕΛ͜͏͠·ͨ͠ 要するに Proc͕એݴ͞Εͨͱ͖ͷϨγʔόʔΛ ޙ͔Β࿔͘Δ͜ͱ͕ग़དྷΕ͹ ΍Γ͍ͨ͜ͱΛୡ੒

Slide 44

Slide 44 text

RubyͷProcͷ͋ΕΛ͜͏͠·ͨ͠ 出来るの?

Slide 45

Slide 45 text

RubyͷProcͷ͋ΕΛ͜͏͠·ͨ͠ 出来るの? それ、Proc#bindingで出来るよ!

Slide 46

Slide 46 text

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


Slide 47

Slide 47 text

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


Slide 48

Slide 48 text

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宣言時のレシーバーが取れている ことが分かる

Slide 49

Slide 49 text

RubyͷProcͷ͋ΕΛ͜͏͠·ͨ͠ ここまでを踏まえて

Slide 50

Slide 50 text

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

Slide 51

Slide 51 text

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)

Slide 52

Slide 52 text

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

Slide 53

Slide 53 text

ςΩετ ⾠஫ҙͱ·ͱΊ ▸ ࠓճ͸Ҿ਺͕̎ݸͷ৔߹͚ͩͰ͕͢ɺՄม௕Ҿ਺Λ͔ͭ͑ ͹೚ҙͷ਺ͷҾ਺Ͱ΋࣮ݱՄೳʢͳഺʣ ▸ _1, _2…ͱ͍͏ϝιου͸࢖͍ऴΘͬͨΒফͨ͠΄͏͕ྑ͍ ▸ proc.binding.receiveʹɺ_1, _2…ͱ͍͏ϝιου͕ݩ͔Β ͋ΔͱյΕΔ ▸ binding͍͢͝

Slide 54

Slide 54 text

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

Slide 55

Slide 55 text

RubyのProcのレシーバ を 壊 しました