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
最新コメント