ruby - versiones - php 7 manual
¿Hay algo así como generadores de Python en Ruby? (4)
Soy nuevo en Ruby, ¿hay alguna forma de yield
valores de las funciones de Ruby? Si es así, ¿cómo? Si no, ¿cuáles son mis opciones para escribir código perezoso?
He visto las Fibers utilizadas de esa manera, mire un ejemplo de este artículo :
fib = Fiber.new do
x, y = 0, 1
loop do
Fiber.yield y
x,y = y,x+y
end
end
20.times { puts fib.resume }
La palabra clave de yield
de Ruby es algo muy diferente de la palabra clave de Python con el mismo nombre, así que no te confundas. La palabra clave de yield
de Ruby es azúcar sintáctica para llamar a un bloque asociado con un método.
El equivalente más cercano es la clase Enumerator de Ruby. Por ejemplo, el equivalente de Python:
def eternal_sequence():
i = 0
while True:
yield i
i += 1
Es esto:
def eternal_sequence
Enumerator.new do |enum|
i = 0
while true
enum.yield i # <- Notice that this is the yield method of the enumerator, not the yield keyword
i +=1
end
end
end
También puede crear Enumeradores para los métodos de enumeración existentes con enum_for
. Por ejemplo, (''a''..''z'').enum_for(:each_with_index)
le proporciona un enumerador de las letras minúsculas junto con su lugar en el alfabeto. each_with_index
esto de forma gratuita con los métodos estándar de Enumerable como each_with_index
en 1.9, por lo que puedes escribir (''a''..''z'').each_with_index
para obtener el enumerador.
Ruby admite generadores de Enumerable::Generator
con Enumerable::Generator
:
require ''generator''
# Generator from an Enumerable object
g = Generator.new([''A'', ''B'', ''C'', ''Z''])
while g.next?
puts g.next
end
# Generator from a block
g = Generator.new { |g|
for i in ''A''..''C''
g.yield i
end
g.yield ''Z''
}
# The same result as above
while g.next?
puts g.next
end
https://ruby-doc.org/stdlib-1.8.7/libdoc/generator/rdoc/Generator.html
Si buscas generar valores de forma perezosa, la respuesta de @ Chuck es la correcta.
Si busca iterar perezosamente sobre una colección, Ruby 2.0 introdujo el nuevo enumerador .lazy
.
range = 1..Float::INFINITY
puts range.map { |x| x+1 }.first(10) # infinite loop
puts range.lazy.map { |x| x+1 }.first(10) # [2, 3, 4, 5, 6, 7, 8, 9, 10, 11]