palabras - ¿Qué significa la palabra clave "yield" en Ruby?
traducir al español (8)
Encontré el siguiente código de Ruby:
class MyClass
attr_accessor :items
...
def each
@items.each{|item| yield item}
end
...
end
¿Qué hace each
método? En particular, no entiendo lo que hace el yield
.
Como cpm dijo que tomó el bloque y lo ejecutó
Ejemplo simple:
def my_method
yield
end
my_method do
puts "Testing yield"
end
Testing yield
=> nil
Como novato, mirar varias respuestas me confundió hasta que respondí la respuesta de Abhi.
el comando de rendimiento pausa el ejecutar 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 me lo aclaró:
def hello
puts "hello"
yield
puts "world"
end
hello do
puts "there"
end
Salida:
Hola
ahí
mundo
Cuando escribe un método que toma un bloque, puede usar la palabra clave yield
para ejecutar el bloque.
Como ejemplo, each
podría haberse implementado en la clase Array de esta manera:
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 elementos de la instancia, pasando el elemento actual como un argumento.
Puede ser usado así:
instance = MyClass.new
instance.items = [1, 2, 3, 4, 5]
instance.each do |item|
puts item
end
De acuerdo con mi comprensión, el rendimiento 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}"}
Salida:
Se llamará un rendimiento con id de 12
Me llaman por nombre de rendimiento 12
Se llamará un rendimiento con id de 14
Me llaman por nombre de rendimiento 14
¿Cómo funciona el rendimiento?
Por lo tanto, cuando la función de name
ejecuta dondequiera que se produzca el rendimiento, se ejecuta el código de bloque. ¿Cuál es el name {|i| puts "I am called by yield name #{i}"}
name {|i| puts "I am called by yield name #{i}"}
Puede ver que hay un yield 12
palabra yield 12
rendimiento ejecuta el código dentro del bloque que pasa 12 como valor de i
.
Aquí hay un ejemplo de juego:
def load_game
puts "Loading"
yield
end
load_game { puts "Game loaded" }
Esto imprimirá el game loaded
justo después de imprimir la loading
:
Cargando
Juego cargado
El efecto neto es que llamar .each a una instancia de MyClass es lo mismo que llamar .each a los elementos de esa instancia.
Este es un ejemplo de desarrollo de su código de muestra:
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
gira sobre una colección. En este caso, está girando sobre cada elemento en la matriz @items
, inicializado / creado cuando hice la new(%w[abcd])
instrucción new(%w[abcd])
.
yield item
en el método MyClass.each
pasa el item
al bloque adjunto a my_class.each
. El item
está cediendo se asigna a la y
local.
¿Eso ayuda?
Ahora, aquí hay un poco más sobre cómo funciona each
. Usando la misma definición de clase, aquí hay un 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>''
Observe que en la última el iterador cayó al final de la matriz. Esta es la trampa potencial para NO usar un bloque porque si no sabes cuántos elementos hay en el conjunto, puedes pedir demasiados elementos y obtener una excepción.
El uso de each
con un bloque @items
sobre el receptor @items
y se detendrá cuando alcance el último elemento, evitando el error y manteniendo las cosas limpias y agradables.
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 hay una buena explicación que lo explica mejor de lo que alguna vez podría hacerlo.
yield
le dice a ruby que llame al bloque pasado al método, dándole su argumento.
yield
producirá un error si el método no se llamó con un bloque donde la declaración de return
no produce error.
return
solo puede enviar valores individuales donde, como Yield
objeto devuelve valores enormes.