ブロックについて
オブジェクト.メソッド名 do |ブロック変数|
ブロック定義本体
end
do〜endの代わりに {〜} でもOK
オブジェクト.メソッド名{|ブロック変数|
ブロック定義本体
}
ブロックを受け取るメソッドの作成
yieldを使ってみる
ブロック定義本体を実行するには「yield」を利用する。
def block_test
5.times {yield()}
end
block_test{
puts "ブロック本体"
}
実行結果
ブロック本体
ブロック本体
ブロック本体
ブロック本体
ブロック本体
ブロックを宣言しない場合はエラーとなる。
ブロック宣言しない
def block_test
5.times {yield()}
end
block_test
実行結果
block_test.rb:2:in `block in block_test': no block given (yield) (LocalJumpError)
ブロックの有無は「block_given?」で判定が行える。
ブロックの有無
def block_test
if block_given?
5.times {yield()}
else
puts "ブロックは宣言されていません"
end
end
block_test
block_test{
puts "ブロック本体"
}
実行結果
ブロックは宣言されていません
ブロック本体
ブロック本体
ブロック本体
ブロック本体
ブロック本体
ブロック変数を使ってみる
yield
に値を渡すことでブロック変数を使用できる。
ブロック変数を使う
def block_test
if block_given?
5.times {|i| yield(i)}
else
puts "ブロックは宣言されていません"
end
end
block_test
block_test{|j|
puts "ブロック本体#{j}"
}
実行結果
ブロックは宣言されていません
ブロック本体0
ブロック本体1
ブロック本体2
ブロック本体3
ブロック本体4
メソッドに引数を定義する
メソッドに引数を定義できる
メソッドに引数を定義
def block_test(t)
if block_given?
t.times {|i| yield(i)}
else
puts "ブロックは宣言されていません#{t}"
end
end
block_test(9)
block_test(3){|j|
puts "ブロック本体#{j}"
}
実行結果
ブロックは宣言されていません9
ブロック本体0
ブロック本体1
ブロック本体2
ブロックをProcとして受け取る
ブロックをProcとして受け取る
def block_test(t, &block)
if block
t.times {|i| block.call(i)}
else
puts "ブロックは宣言されていません#{t}"
end
end
block_test(9)
block_test(3) do |j|
puts "ブロック本体#{j}"
end
実行結果
ブロックは宣言されていません9
ブロック本体0
ブロック本体1
ブロック本体2
Procを渡す
Proc.new
でProcを生成してcall
メソッドで実行する。
Procを渡す
def block_test(t, f=nil)
if f
t.times {|i| f.call(i)}
else
puts "Procは渡されていません#{t}"
end
end
procTest = Proc.new{|j|
puts "Proc本体#{j}"
}
block_test(9)
block_test(3, procTest)
実行結果
Procは渡されていません9
Proc本体0
Proc本体1
Proc本体2
Procオブジェクトを「&変数名」でブロックとして渡す
指摘を受けての追記
Procオブジェクトをブロックとして渡す
def block_test(t)
if block_given?
t.times { |i| yield(i) }
else
puts "ブロックは宣言されていません#{t}"
end
end
procTest = Proc.new{|j|
puts "ブロック本体#{j}"
}
block_test(9)
block_test(3, &procTest)
実行結果
ブロックは宣言されていません9
ブロック本体0
ブロック本体1
ブロック本体2
&
をつけて渡すとブロックとして認識してくれるので呼び出されるメソッド側はそのままでも大丈夫なんですね。
最初のは色々と余計なことをしているようでこちらのがスッキリしてますね。