"Austin Ziegler" <halostatue / gmail.com> schrieb im Newsbeitrag
news:9e7db9110504250552129835ec / mail.gmail.com...
> On 4/25/05, Roshan James <roshanj / microsoft.com> wrote:
> > How are iterators implemented in Ruby?
> >
> > Sometime back I had asked a questuin about invoking iterators in
> > locksteps and I was told that iterators in ruby are implemented as
> > closures that are passed to the called method.

The iterator is not the closure.  The closure (aka block) is just for
executing some piece of code on each element it's given.  The iteration
itself is typically implemented in #each (or any other method).  Most of
the time (i.e. if you do not use Generator) you cannot access an iterator.
You just have a method that accepts a block.

You can easily implement an iteration yourself, like

class Demo
  def initialize(st,en) @start, @end = st, en end

  def each
    i = @start

    while i <= @end
      yield i
      i += 1
    end

    self
  end
end

>> Demo.new(1,5).each {|x| puts x}
1
2
3
4
5
=> #<Demo:0x1018f118 @end=5, @start=1>

> If iterators are
> > passed as closures then, 1) Every consumer of the iterator should
> > undergo closure conversion in some way

I'm not sure what you're getting at here.  Since there is no iterator I'd
say that in itself is reason enough that there is no closure conversion.
:-)  Other than that, I don't see why a closure should be converted.
Maybe I'm lacking understanding of other languages.

> > 2) How is "break"
> > implemented ? This similar to how it would be done in Scheme or
> > similar language that inherently supports closures.

Does this illustrate the behavior?

>> Demo.new(1,5).each {|x| puts x; break "end" if x == 4}
1
2
3
4
=> "end"

"break" simply terminates the iterating method (#each in this case) and
forces return of the provided value (if there is any, nil is the default).

> > I was reading about CLU (the parent language for the iterator
> > concept), and they implemnted iterators on a single stack. I
> > believe that that would involve have caller and callee function
> > frames to live on the stack at the same time. The iteration would
> > be implemnetd as goto between these functions with a corresposding
> > shift in stock location to refernce locals. This implementation
> > has the inherent limitation of not being able to do multiple
> > itetarors in lock step.

No, we actually have a method call here.  That's quite obvious if you
choose the other alternative for the implementation:

class Demo
  def each2(&b)
    i = @start

    while i <= @end
      b.call( i )
      i += 1
    end

    self
  end
end

>> Demo.new(1,5).each2 {|x| puts x}
1
2
3
4
5
=> #<Demo:0x1016cd20 @end=5, @start=1>


> > Another alternative is that the itetror is converted to an object
> > that maintains state - a classical generator. This is what C# and
> > Py do.
> >
> > How does Ruby do iterators ?
>
> What I'm getting ready to tell you is as far as I understand it; it
> may not be completely correct -- and the most authoritative way to
> see this is the source.
>
> That said, simple iterators like #each implement a loop through the
> container and yield the object in the iterator to the provided code
> block. #each suspends execution until the block (closure) finishes
> executing. That would generally indicate a change in stack frame.

Yes, you can view a block as an anonymous callback function.

> Ruby does have generators available, but they're overkill for ~95%
> of cases.

Perfectly agree.

Kind regards

    robert