2010-12-01 25 views

Respuesta

30

Este es un ejemplo dar contenido a su código de ejemplo:

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 bucles más de una colección. En este caso, está girando sobre cada elemento en la matriz @items, inicializado/creado cuando hice la instrucción new(%w[a b c d]).

yield item en el método MyClass.each pasa item al bloque unido a my_class.each. El item cedido se asigna al local y.

¿Eso ayuda?

Ahora, aquí hay un poco más sobre cómo funciona each. Utilizando la misma definición de clase, aquí hay algo de código:

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

en cuenta que en el último next el iterador se cayó de la final de la matriz. Esta es la trampa potencial para NOT usando un bloque porque si no sabe cuántos elementos hay en la matriz, puede solicitar demasiados elementos y obtener una excepción.

El uso de each con un bloque se repetirá sobre el receptor @items y se detendrá cuando llegue al último elemento, evitando el error y manteniendo las cosas limpias.

+0

Muchas gracias! –

3

El efecto neto es que llamar .each en una instancia de MyClass es lo mismo que llamar a .each en los elementos de esa instancia.

10

Un método de Ruby que recibe un bloque de código lo invoca llamándolo con la palabra clave yield. Se puede usar para iterar sobre una lista, pero no es un iterador como el que se encuentra en otros idiomas.

Here es una buena explicación que lo explica mejor de lo que alguna vez podría hacerlo.

+0

¡Gracias por el enlace! –

+2

fwiw - Encontré [esta página] (http://www.tutorialspoint.com/ruby/ruby_blocks.htm) para dar una explicación más simple de {code} yield {code} específicamente – JoeyC

+3

El enlace no funciona :( –

14

Cuando escribe un método que requiere un bloque, puede usar la palabra clave yield para ejecutar el bloque.

A modo de ejemplo, each podrían haberse implementado en la clase Array así:

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

MyClass#each toma un bloque. Ejecuta ese bloque una vez para cada elemento en la matriz de la instancia items, pasando el elemento actual como un argumento.

Podría ser utilizado como esto:

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

¡Muchas gracias! –

2

como cpm dijo que su tomando el bloque y ejecutarlo

def my_method 
    yield 
end 


my_method do 
    puts "Testing yield" 
end 

Testing yield 
=> nil 
4

yield dice rubí llamar el bloque pasado al método, dándole su argumento.

yield producirá un error si el método no se llamó con un bloque donde como return instrucción no produce un error.

return sólo puede enviar valores individuales donde como Yield retorno de los valores objeto enormes.

3

Como novato, mirando a través de varias de las respuestas me confundió hasta que llegue a la respuesta de Abhi.

el comando de rendimiento hace una pausa ejecutando el código en el método, y en su lugar pasa el control nuevamente al bloque de código que lo llamó, ejecuta ese código y luego continúa ejecutando el resto del método después de eso. Aquí hay un ejemplo que aclara que para mí:

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

hello do 
    puts "there" 
end 

Salida:

hola

no

mundo

1

acuerdo con mi rendimiento comprensión ejecuta el código del bloque.

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}"} 

de salida:

un rendimiento será llamada con id de 12

estoy llamado por nombre rendimiento del 12

un rendimiento será llamada con id de 14

Me llaman por nombre de rendimiento 14

Cómo rendimiento funciona?

Por lo tanto, cuando la función name se ejecuta donde se produce el rendimiento, se ejecuta el código de bloque. Cuál es name {|i| puts "I am called by yield name #{i}"}

Usted puede ver que hay una palabra yield 12 rendimiento ejecuta el código dentro del bloque que pasa 12 como valor de i.

Aquí está un ejemplo de juego para él:

def load_game 
    puts "Loading" 

    yield 

end 


load_game { puts "Game loaded" } 

Esto imprimirá game loaded justo después de la impresión loading:

Cargando

juego Loaded

Cuestiones relacionadas