6. ブロックをオブジェクト化
hello1 = Proc.new do % ruby sample2.rb
puts "Hello, world" Hello, world
puts "Hello, world" Hello, world
puts "Hello, world" Hello, world
end Hello, world
Hello, world
hello2 = proc do Hello, world
puts "Hello, world" Hello, world
puts "Hello, world" Hello, world
puts "Hello, world" Hello, world
end
hello3 = lambda do
puts "Hello, world"
puts "Hello, world"
puts "Hello, world" 解説ポイント
end •Proc.newとprocと
hello1.call lambdaの違い
hello2.call
hello3.call •callで呼び出される
7. ブロックを関数のように
sum = lambda {|x,y|
x + y % ruby sample3.rb
} 5
puts sum.call(2,3)
解説ポイント
•できることはわかっ
たけど、どういう時
に便利かなぁ。
8. ブロック付メソッド呼出
class Foo
def three(&arg) % ruby sample4.rb
arg.call Hello world
yield Hello world
yield Hello world
end
end
foo=Foo.new
foo.three{ 解説ポイント
puts "Hello world"
} •単に3回ブロックの中を繰り返す
だけのメソッド
•yieldでメソッドの中からブロッ
クが呼び出されるのがキモ
9. ブロックに引数を渡す
class Foo % ruby sample5.rb
def my_logger(filepath,&arg) Hello world
file=open(filepath,"w")
arg.call(file) % cat log.txt
file.close Hello world logging.
end
end
foo=Foo.new
foo.my_logger("log.txt"){|file|
puts "Hello world"
file.write "Hello world logging.n"
}
解説ポイント
•ブロックの中で使えるロガーもどき
•繰り返しだけがブロックではないという気合い
10. Procをメソッドに渡す
class Foo class Foo
def my_logger(filepath) def my_logger(filepath)
file=open(filepath,"w") file=open(filepath,"w")
yield(file) yield(file)
file.close file.close
end end
end end
foo=Foo.new foo=Foo.new
script=proc{|file| foo.my_logger("log.txt"){|file|
puts "Hello world" puts "Hello world"
file.write "Hello world logging.n" file.write "Hello world logging.n"
} }
foo.my_logger("log.txt",&script)
% ruby sample6.rb 解説ポイント
Hello world
•ブロックの代わりにブロックオブジェクトを渡
% cat log.txt せる。
Hello world logging.
•&をつける必要あり。
12. Symbol#to_proc
マニュアルより
# The same as people.collect { |p| p.name }
people.collect(&:name)
# The same as people.select { |p| p.manager? }.collect { |p| p.salary }
people.select(&:manager?).collect(&:salary)
ソースはたったの1行
class Symbol
def to_proc
Proc.new { |*args| args.shift.__send__(self, *args) }
end
end
とっても便利で、冗長だった
部分がDRYで嬉しいんだけ
ど、なんでこうなるの???
13. to_procってそもそも?
マニュアルより
to_proc メソッドを持つオブジェクトならば、`&' 修飾した引数として渡すことができます
(デフォルトで Proc、Method オブジェクトは共に to_proc メソッドを持ちます)。to_proc
はメソッド呼び出し時に実行され、Proc オブジェクトを返すことが期待されます。
class Foo
def to_proc
Proc.new {|v| p v} つまりブロックに渡すと
end
end to_procの中身をブロックの
[1,2,3].each(&Foo.new)
代わりに実行する。
=> 1
2
3
14. Symbol#to_procは
class Symbol
def to_proc
Proc.new { |*args| args.shift.__send__(self, *args) }
end
end
==>> user.__send__(:email) の繰り返しになる
よーく見ると、args[0]をsendしている。
selfは呼出し元なので、下の場合は:emailになる。
User.find(:all).map{|user|user.email}
と
User.find(:all).map(&:email)
が等価になる。
なんでシンボルを与えて、メソッドが
返って来るかがわかる。
send(:email)ってな具合に評価されるよ!ってのを
覚えておくといいと思います。
modelに独自メソッドを定義した時も呼び出せます。