1. ホーム
  2. スクリプト・コラム
  3. ルビートピックス

Rubyブロックチュートリアル

2022-01-30 08:17:20

1. ブロックとは
Rubyでは、{}やdo.の間にあるコードは、"Ruby "と呼ばれます。.end の間にあるコードがブロックです。コードブロックは、メソッドの最後の引数の直後の同じ行のメソッドの後にのみ表示でき、yield キーワードによって呼び出されます。例を挙げます。

[1,2,3,4,5].each { |i| puts i }

[1,2,3,4,5].each do |i| 
puts i
end



ブロック変数です。yieldキーワードでブロックを呼び出すと引数を渡すこともでき、ブロック内の縦線(|)の間に与えられた引数名はyieldからの引数を受け取るために使われます。

 縦線の間にある変数(上の例では|i|のような)はブロック変数と呼ばれ、通常のメソッドの引数のように動作する

2. コードブロックを使いこなす
最も一般的で、最もシンプルで、最も議論を呼んだ、そして最もRuby的な方法は、blocksです。

array = [1, 2, 3, 4]

array.collect! do |n|
 n ** 2
end

puts array.inspect

# => [1, 4, 9, 16]



do...endがブロックを形成し、そのブロックがcollect!!!を介して配列に渡されます。ブロックの中でnを使えば、配列の各要素を繰り返し処理することができます。

collect!はRubyのライブラリにあるメソッドなので、似たようなメソッドであるiterate!を自作してみよう。

class Array
 def iterate!
  self.each_with_index do |n, i|
   self[i] = yield(n)
  end
 end
end

array = [1, 2, 3, 4]

array.iterate! do |n|
 n ** 2
end

puts array.inspect

# => [1, 4, 9, 16]



まず、Arrayを開いて、iterate! メソッドを追加します。で終わるメソッド名は、危険なメソッドであることを示し、注意を喚起する。これで、collect! の時と同じようにiterate! を使える可能性が出てきました。

プロパティと違って、メソッド内でブロック名を指定する必要はなく、yieldを使って呼び出す。 yieldはブロック内のコードを実行する。また、yieldにn(each_with_indexが現在処理している番号)を渡していることに注目してください。yieldに渡された引数は、ブロック内の引数(||の部分)に対応しています。これでnはブロックから呼び出され、yieldの呼び出しでn**2を返すことができる。
呼び出し全体は次のようになります。
1. 整数の配列はiterateを呼び出す!
2. yieldが呼ばれたら、n(1回目は1、2回目は2、...)を渡してブロックする
3. block は n に対して n**2 を行う。最後の行なので、自動的にそれが結果として返される。
4. yieldはblockの結果を取得し、その値を配列に書き換えます。
5. 5. データ内の各オブジェクトは同じ操作を行う。

3. {とdo... ...endは優先順位が異なる

ブロックを渡すとき、{}で渡されたブロックはdo...endより優先順位が高いです。

曖昧さを避けるために、引数は()で囲むとよいでしょう。例えば

1.upto 3 do |x|

puts x

end



は正しいのですが、1.upto 3 {|x| puts x} は正しくコンパイルされません。

理由を教えてください。

1. upto 3 do...endのブロックはuptoメソッド内で渡され、3はuptoのパラメータとして渡されます。

1.upto 3 {|x| puts x} この文は、3を関数名として扱い、この関数にブロックを渡し、その戻り値をuptoメソッドの引数としているので、コンパイルはできますが、()を追加する必要があります。