yieldとブロック引数でイテレータ

yield

  • イテレータを定義する為に使用する。
  • yieldに渡されたデータはブロック変数に代入される
def foo
  yield(1,2)
end

foo do |a, b|
  p a              #=> 1
  p b              #=> 2
end 

ブロック引数

  • これもイテレータを定義するときに使用する。
  • 引数の頭に'&'をつける。
  • callメソッドに渡したデータがブロック変数に代入される。
  • '&block'と'block = Proc.new'は同じ事(?)
def foo(&block)
  block.call(1,2)
end

foo do |a, b|
  p a              #=> 1
  p b              #=> 2
end 

Array#eachっぽいのを書いてみた(超簡易版)

a = []
for i in 1..100
  a << i
end

#
# yield
#
def foo1(x = [])
  index = 0
  while index < x.size
    yield x[index]
    index += 1
  end
end

sum = 0
foo1(a) { |f| sum += f }
puts sum


#
# block argument
#
def foo2(z = [], &block)
  index = 0
  while index < z.size
    block.call z[index]
    index += 1
  end
end

sum = 0
foo2(a) { |f| sum += f }
puts sum

Rubyリファレンスマニュアルみてたら、ほぼ同じ例が載ってた><


ちなみにメソッドの仮引数は以下の順に記述しないといけない。

  1. デフォルト式のない引数(複数指定可)
  2. デフォルト式のある引数(複数指定可)
  3. * を伴う引数(1つだけ指定可)
  4. & を伴う引数(1つだけ指定可)

なので次のように書くとエラー。

def foo2(&block, z = [])


まだ、両者の使い分けをどうしたら良いのかよくわからん。