In C #, you can do something like this:
public IEnumerable<T> GetItems<T>() { for (int i=0; i<10000000; i++) { yield return i; } }
This returns an enumerated sequence of 10 million integers without allocating such a length in memory.
Is there a way to do the equivalent thing in Ruby? The specific example I'm trying to solve is smoothing a rectangular array into a sequence of values ββto be enumerated. The return value should not be Array or Set , but rather some sequence that can only be repeated / listed in order, not an index. Therefore, the entire sequence should not be allocated in memory at the same time. In .NET, these are IEnumerable and IEnumerable<T> .
Any clarification of the terminology used here in the Ruby world would be helpful, as I am more familiar with .NET terminology.
EDIT
Perhaps my initial question is not entirely clear - I think the fact that yield has very different meanings in C # and Ruby is the cause of the confusion here.
I don't need a solution that requires my method to use a block. I want a solution that has an actual return value. The return value allows convenient sequence processing (filtering, projecting, concatenation, zipping, etc.).
Here is a simple example of how I can use get_items :
things = obj.get_items.select { |i| !i.thing.nil? }.map { |i| i.thing }
In C #, any method that returns IEnumerable that uses yield return causes the compiler to generate a state machine behind the scenes that is suitable for this behavior. I suspect something like this could be achieved using Ruby extensions, but I have not seen an example and do not quite understand how this will be done.
Indeed, it is possible that I can use Enumerable to achieve this. A simple solution would be for us Array (including the Enumerable module), but I do not want to create an intermediate collection with N elements in memory, when you can simply provide them lazily and avoid a burst of memory at all.
If this still doesn't make sense, consider the above code example. get_items returns the enumeration on which select is invoked. What is passed to select is an instance that knows how to provide the next element in the sequence whenever necessary. It is important to note that the entire set of items has not yet been calculated. Only when select needs an element will it ask for it, and the hidden code in get_items will act and provide it. This laziness is carried along the chain, so select only draws the next element from the sequence when map requests it. Thus, a long chain of operations can be performed simultaneously on one data element. In fact, code structured in this way can even process an infinite sequence of values ββwithout any memory errors.
So, this type of laziness is easily encoded in C #, and I don't know how to do it in Ruby.
I hope that is clearer (I will try not to write questions in 3AM in the future).