Ruby

Ruby ブロック

More than 1 year has passed since last update.


ブロックについて

オブジェクト.メソッド名 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

&をつけて渡すとブロックとして認識してくれるので呼び出されるメソッド側はそのままでも大丈夫なんですね。

最初のは色々と余計なことをしているようでこちらのがスッキリしてますね。