2010-12-01 3 views

答えて

30

これはあなたのサンプルコードを肉付け例です。

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。この場合、new(%w[a b c d])ステートメントを実行したときに初期化/作成された@items配列の各項目がループしています。

yield itemMyClass.eachの方法は、my_class.eachに取り付けられたブロックにitemを渡す。得られたitemは、ローカルyに割り当てられます。

これは役に立ちますか?

ここで、eachの仕組みについてもう少し詳しくお話します。最後nextにイテレータは、配列の終わりから落ちたこと

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>' 

注意:同じクラス定義を使用して、ここでいくつかのコードです。これはブロックを使用するではなくの潜在的な落とし穴です。なぜなら、配列に含まれる要素の数がわからないと、余りにも多くのアイテムを要求して例外を得ることができるからです。

ブロックにeachを使用すると、@itemsレシーバーで繰り返し処理され、最後のアイテムに到達するとエラーが回避され、すばらしいクリーンな状態が維持されます。

+0

ロード

を読み込んで

ゲームはどうもありがとうございました! –

3

実際の効果は、MyClassのインスタンスで.eachを呼び出すことは、そのインスタンスの.itemで.eachを呼び出すことと同じです。

10

コードブロックを受け取るRubyメソッドは、yieldキーワードを使用して呼び出します。それはリストを反復するのに使うことができますが、他のいくつかの言語で見つけるもののような反復子ではありません。

Hereは、私がこれまで以上に優れた説明をする良い説明です。

+0

リンクありがとうございます! –

+2

fwiw - 具体的には{code} yield {code}の簡単な説明を与えるために[このページ](http://www.tutorialspo.com/ruby/ruby_blocks.htm)が見つかりました – JoeyC

+3

リンクが機能しません:( –

14

ブロックを使用するメソッドを記述するときは、yieldキーワードを使用してブロックを実行できます。

例として、eachは、このような配列のクラスに実装されている可能性が:

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

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

それはこのように使用されることがあります。

instance = MyClass.new 
instance.items = [1, 2, 3, 4, 5] 
instance.each do |item| 
    puts item 
end 
+0

どうもありがとうございました! –

2

CPMはそのブロックを取って、それを実行に述べたように

def my_method 
    yield 
end 


my_method do 
    puts "Testing yield" 
end 

Testing yield 
=> nil 
4

yieldはそれにそのを与え、メソッドに渡されたブロックを呼び出すためにルビーを伝えます引数。

yieldは、returnステートメントでエラーが発生しないブロックでメソッドが呼び出されなかった場合にエラーを生成します。

returnは、値がYieldの大きな値を返すような単一の値しか送信できません。

3

初心者として、私がアビの答えを打つまで、多くの答えを見て私を混乱させました。

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

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

hello do 
    puts "there" 
end 

出力:私の理解収量によると

ハロー

世界

1

ブロックからコードを実行します。

def name 
    puts "A yield will be called with id of 12" 
    yield 12 
    puts "A yield will be called with id of 14" 
    yield 14 
end 


name {|i| puts "I am called by yield name #{i}"} 

出力:

収率は私が12

収率は14

のIDで呼び出される降伏名前で呼ばれています12

のIDで呼び出されます私は収穫名で呼ばれています14

どのように収穫作品ですか?

したがって、ブロックコードが実行されるとどこでも、name関数が実行されます。 name {|i| puts "I am called by yield name #{i}"}

yield 12 yieldがiの値として12を渡すブロック内のコードを実行することがわかります。ここで

はそれのためのゲームの例である:

def load_game 
    puts "Loading" 

    yield 

end 


load_game { puts "Game loaded" } 

この権利loadingを印刷した後game loadedを印刷します:

関連する問題