versión versiones php7 php5 entre diferencias características cambios cada actualizar ruby lazy-evaluation

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]