I am new to Ruby, is there a way to yield
values from Ruby functions? If yes, how? If not, what are my options to write lazy code?
Ruby provides a script called Generator. This script can be used to generate many useful items in Rails.
Generators allow you to create iterators in a very pythonic manner. Iterators allow lazy evaluation, only generating the next element of an iterable object when requested. This is useful for very large data sets. Iterators and generators can only be iterated over once.
In Python, yield is a keyword that turns a function into a generator. Unlike a list, a generator does not store values. Instead, it knows the current value and how to get the next one. This makes a generator memory-efficient.
Python generators are a simple way of creating iterators. All the work we mentioned above are automatically handled by generators in Python. Simply speaking, a generator is a function that returns an object (iterator) which we can iterate over (one value at a time).
Ruby's yield
keyword is something very different from the Python keyword with the same name, so don't be confused by it. Ruby's yield
keyword is syntactic sugar for calling a block associated with a method.
The closest equivalent is Ruby's Enumerator class. For example, the equivalent of the Python:
def eternal_sequence(): i = 0 while True: yield i i += 1
is this:
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
You can also create Enumerators for existing enumeration methods with enum_for
. For example, ('a'..'z').enum_for(:each_with_index)
gives you an enumerator of the lowercase letters along with their place in the alphabet. You get this for free with the standard Enumerable methods like each_with_index
in 1.9, so you can just write ('a'..'z').each_with_index
to get the enumerator.
I've seen Fibers used in that way, look at an example from this article:
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 }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With