37

次のRubyコードに遭遇しました。

class MyClass
    attr_accessor :items
    ...
    def each
        @items.each{|item| yield item}
    end
    ...
end

メソッドは何をしeachますか?特に、何をしているのかわかりませんyield

4

8 に答える 8

35

これは、サンプル コードを具体化する例です。

class MyClass
  attr_accessor :items

  def initialize(ary=[])
    @items = ary
  end

  def each
    @items.each do |item| 
      yield item
    end
  end
end

my_class = MyClass.new(%w[a b c d])
my_class.each do |y|
  puts y
end
# >> a
# >> b
# >> c
# >> d

eachコレクションをループします。この場合、ステートメントを実行@itemsしたときに初期化/作成された、配列内の各項目をループしています。new(%w[a b c d])

yield itemメソッド内の は、 に接続されたブロックにMyClass.each渡されます。譲り受けたものは local に割り当てられます。itemmy_class.eachitemy

それは役に立ちますか?

さて、ここでもう少し仕組みについて説明eachします。同じクラス定義を使用して、いくつかのコードを次に示します。

my_class = MyClass.new(%w[a b c d])

# This points to the `each` Enumerator/method of the @items array in your instance via
#  the accessor you defined, not the method "each" you've defined.
my_class_iterator = my_class.items.each # => #<Enumerator: ["a", "b", "c", "d"]:each>

# get the next item on the array
my_class_iterator.next # => "a"

# get the next item on the array
my_class_iterator.next # => "b"

# get the next item on the array
my_class_iterator.next # => "c"

# get the next item on the array
my_class_iterator.next # => "d"

# get the next item on the array
my_class_iterator.next # => 
# ~> -:21:in `next': iteration reached an end (StopIteration)
# ~>    from -:21:in `<main>'

next最後に、反復子が配列の末尾から外れていることに注意してください。これは、ブロックを使用しない場合の潜在的な落とし穴です。配列に含まれる要素の数がわからない場合、あまりにも多くの項目を要求して例外が発生する可能性があるためです。

ブロックで使用eachすると、レシーバーを繰り返し処理し@items、最後のアイテムに到達すると停止し、エラーを回避し、物事をきれいに保ちます。

于 2010-12-01T07:41:39.403 に答える
17

ブロックを受け取るメソッドを記述する場合、yieldキーワードを使用してブロックを実行できます。

例として、次のeachように Array クラスに実装できます。

class Array
  def each
    i = 0
    while i < self.size
      yield( self[i] )
      i = i + 1
    end
  end
end

MyClass#eachブロックを取ります。インスタンスの配列内の項目ごとにそのブロックを 1 回実行しitems、現在の項目を引数として渡します。

次のように使用できます。

instance = MyClass.new
instance.items = [1, 2, 3, 4, 5]
instance.each do |item|
  puts item
end
于 2010-12-01T08:08:59.573 に答える
10

yieldコード ブロックを受け取る Ruby メソッドは、キーワードを指定して呼び出して呼び出します。リストを反復処理するために使用できますが、他の言語で見られるような反復子ではありません。

これは、私がこれまで以上に説明できる優れた説明です。

于 2010-12-01T07:42:28.780 に答える
4

最終的な効果は、MyClass のインスタンスで .each を呼び出すことは、そのインスタンスの .items で .each を呼び出すことと同じです。

于 2010-12-01T06:27:59.980 に答える
4

初心者として、アビの答えにたどり着くまで、多くの答えを見て混乱しました。

yield コマンドは、メソッド内のコードの実行を一時停止し、代わりにそれを呼び出したコードのブロックに制御を戻し、そのコードを実行し、その後メソッドの残りの実行を続行します。これを明確にした例を次に示します。

def hello
    puts "hello"
    yield 
    puts "world"
end

hello do
    puts "there"
end 

出力:

こんにちは

そこの

世界

于 2016-09-11T05:47:05.890 に答える
3

cpmが言ったように、ブロックを取得して実行します

簡単な例:

def my_method
  yield
end


my_method do
  puts "Testing yield"
end

Testing yield
=> nil 
于 2014-08-20T18:55:41.157 に答える