views:

174

answers:

3

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?

A: 

yield is indeed part of Ruby. It doesn't function exactly the same as in Python.

http://stackoverflow.com/questions/764134/rubys-yield-feature-in-relation-to-computer-science

ghoppe
"Not exactly the same" is quite an understatement. Ruby's `yield` keyword has *absolutely nothing whatsoever* to do with the `yield` keyword in Python. It also has *absolutely nothing whatsoever* to do with this question. (It also has absolutely nothing to do with the usage of `yield` in pretty much any other language or in computer science in general, which is a source of endless confusion, as this answer clearly demonstrates.)
Jörg W Mittag
+5  A: 

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 just 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 num # <- 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.

Chuck
+3  A: 

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 }
Michael Kohl
In fact, in Ruby 1.9's `Enumerator` is implemented using `Fiber`. That was one of the main reasons for adding them, actually, because in Ruby 1.8 `Enumerator`s use continuations, but that is a) rather unwieldy and b) at that time continuations were going to be removed from the Ruby language.
Jörg W Mittag