次のRubyコードに遭遇しました。
class MyClass
attr_accessor :items
...
def each
@items.each{|item| yield item}
end
...
end
メソッドは何をしeach
ますか?特に、何をしているのかわかりませんyield
。
次のRubyコードに遭遇しました。
class MyClass
attr_accessor :items
...
def each
@items.each{|item| yield item}
end
...
end
メソッドは何をしeach
ますか?特に、何をしているのかわかりませんyield
。
これは、サンプル コードを具体化する例です。
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 に割り当てられます。item
my_class.each
item
y
それは役に立ちますか?
さて、ここでもう少し仕組みについて説明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
、最後のアイテムに到達すると停止し、エラーを回避し、物事をきれいに保ちます。
ブロックを受け取るメソッドを記述する場合、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
yield
コード ブロックを受け取る Ruby メソッドは、キーワードを指定して呼び出して呼び出します。リストを反復処理するために使用できますが、他の言語で見られるような反復子ではありません。
これは、私がこれまで以上に説明できる優れた説明です。
最終的な効果は、MyClass のインスタンスで .each を呼び出すことは、そのインスタンスの .items で .each を呼び出すことと同じです。
初心者として、アビの答えにたどり着くまで、多くの答えを見て混乱しました。
yield コマンドは、メソッド内のコードの実行を一時停止し、代わりにそれを呼び出したコードのブロックに制御を戻し、そのコードを実行し、その後メソッドの残りの実行を続行します。これを明確にした例を次に示します。
def hello
puts "hello"
yield
puts "world"
end
hello do
puts "there"
end
出力:
こんにちは
そこの
世界
cpmが言ったように、ブロックを取得して実行します
簡単な例:
def my_method
yield
end
my_method do
puts "Testing yield"
end
Testing yield
=> nil