From: Martin DeMello Date: 2002-11-20T03:29:49+09:00 Subject: Re: Thoughts on generators Hal E. Fulton wrote: > Martin, > > I've only halfway followed this thread, as > I'm not 100% sure in what sense people are > using the term "generator"... if it's in a > pure Python sense, well, my knowledge of > Python is very limited. Mine too - I just had a quick look at python generators, and they seem to be semantically closer to the call/cc solutions proposed in ruby. Unless I've misunderstood it entirely, it's essentially an rubyish internal iterator, but with 'yield' suspending the each method until '.next' is called. My generators are closer in spirit to python's iterators. > Why don't you read the post I made > back in August and see if you think > there's any connection... > > The thread is entitled "Super-iterator? (long)" > and starts at http://ruby-talk.org/46337 > > I was attempting to solve three or four > problems at once (some of which may be > non-problems to other people). One of > these was the lack of "on-demand" iteration > which as I understand it may be the same > as generation. It's not really the same thing. This splits into two parts: 1. Define a set of useful and interesting methods on objects that implement .next (and .end?) - this would be a mixin like Enumerable 2. Define a set of constructors that return nextable objects (which I'm calling generators) based on various other objects. Nextable objects aren't realy a subset or superset of Enumerables, so while a generator can serve as an iterator over some objects, it's not a universal solution to the external iterator problem. OTOH it allows for other interesting cases, like recurrence relations and (somewhat primitive) unidirectional streams. The other neat thing is that each can be built atop next, so you get Enumerable practically for free. Looking at some of your super-iterator motivations: > 1. Sometimes I want to know whether I'm in the first (or last) > iteration of an iterator block. Since the generator is an object, you can add first? and last? methods to it. > 2. Sometimes I want to do things "alternately" (i.e., for every > other iteration). def evens while !end? yield next(2)[0] end end > 3. I'm a tiny bit displeased by the difference between each and > each_with_index. I'd like them to be done by one thing. Not sure what you mean here. What would the one thing do? > 4. Sometimes I want to change an item in an array, for instance. > each won't allow this; I have to use each_with_index and manually > index into the array. Hm - I suppose an accessor would be useful, in cases where it was applicable. I'll have to think about that. > 5. Sometimes an ordinary iterator seems inadequate; I want something > that can grab the next entry on demand, without waiting for the > loop to run around again. Which is what .next is all about - it just won't be applicable in the general case. Of course, you could always pass in obj.to_a, though that would create an intermediate array. martin