ruby1.9.x では Proc#lambda? を使用して Proc が lambda かどうかを判別することが出来る。
ruby1.9.x では lamdba() の定義に -> 記号を使えるようになった。p = ->(x) { x + 1 }
Proc.new() は Proc から戻るのではなく、Procが定義されたスコープに戻る。
Proc.new() は多すぎると越えた分を切り落とし、少なすぎると足りない引数に nil を割りあてる。
ruby1.9.x では lamdba() の定義に -> 記号を使えるようになった。p = ->(x) { x + 1 }
- proc()
- return
Proc.new() は Proc から戻るのではなく、Procが定義されたスコープに戻る。
- 引数の数
Proc.new() は多すぎると越えた分を切り落とし、少なすぎると足りない引数に nil を割りあてる。
# メソッドの一部を呼び出すたびに操作したい場合はメソッドにブロックを渡す # ブロックはメソッドを呼び出した後 do ~ end の中に処理を記述する def hoge puts 'before' yield puts 'after' end hoge do puts 'hoge' end # ブロックが渡されていないのに yield を呼ぶとエラー # hoge # ブロックが渡されているかどうかをチェックするには Kernel.block_given? を使う def moke block_given? ? yield : puts('no block') end moke moke do puts 'moke' end
before hoge after no block moke
def sum(a, b); yield(a, b); end # メソッドの引数列の最後に & 付きの引数を用意すればブロックをProcオブジェクトして受け取ることが出来る。 def hoge a, b, &block puts block.class # block は Proc だがブロックとして扱いたい場合メソッドに渡す時に & を付ければ # Proc からブロックに変換される。 puts sum(a, b, &block) # block は Proc なのでそのままcallすることも出来る。 puts block.call(a, b) end # ブロックをつけずに呼び出すと sum の yield が失敗する。 # hoge(5, 5) hoge(3, 2) {|x, y| x * y}
Proc 6 6
class A def to_proc puts 'call to_proc' Proc.new do |x| puts x end end end # Procオブジェクトをメソッドの最後の引数に & を付けて渡すとブロックを渡すことが出来る。 # Procオブジェクトでないが、戻り値が Proc の to_proc メソッドもっている場合はProc以外でも渡すことが出来る。 obj = A.new puts(&obj) # to_procで生成したProcに引数があれば渡すことも出来る。 [1, 2, 3].each(&obj) class Symbol # Symbolのselfは自分のシンボル文字列が取得できる。 def show; puts self; end # 既に組み込みで定義されているがこんな感じのメソッドが定義されている。 #def to_proc; Proc.new {|x| x.send(self) }; end end :aiueo.show # 引数を受け取り、その引数のメソッドを呼び出すだけのブロックを「ワンコールブロック」という p %w{bob bill heather}.map {|x| x.capitalize } # 上記の Symbol#to_proc を利用するとワンコールブロックを短い記述に置き換えることが出来る。 p %w{bob bill heather}.map(&:upcase) # 引数が二つ以上の引数を受け取るブロックもサポートしている。 p [1, 2, 3].inject(0, &:+)
call to_proc call to_proc 1 2 3 aiueo ["Bob", "Bill", "Heather"] ["BOB", "BILL", "HEATHER"] 6
class C def initialize(value); @x = value; end def show; puts @x; end end obj = C.new(:hoge) # Object#method() を呼び出すとメソッドを Method オブジェクトとして取得できる。 m = obj.method :show # Method#call() で実行できる。 # lamdbaは定義されたスコープ内で評価されるが、Methodは属するオブジェクトのスコープ内で評価される。 m.call # objスコープで評価される。 # オブジェクトからメソッドを引き離すには Method#unbind() を使う unbound = m.unbind puts unbound.class obj2 = C.new(:moke) # UnboundMethodオブジェクトは実行できないが # UnboundMethod#bind() でオブジェクトとひもづければMethodオブジェクトに戻せる。 m2 = unbound.bind(obj2) puts m2.class m2.call # obj2スコープで評価される。 puts '----------------' # MethodからProcに変換したい場合は Method#to_proc() を使用する。 puts m.class puts m.to_proc.class # ブロック(Proc)をメソッドに変換する場合は Module#define_method() を使用する。 p = Proc.new { puts "call Proc: #{@x}" } C.send(:define_method, :show2, p) obj.show2 obj2.show2
hoge UnboundMethod Method moke ---------------- Method Proc call Proc: hoge call Proc: moke
最新コメント