tags:

views:

359

answers:

2

I would appreciate it if someone could help me understand the difference between using a Yielder in an Enumerator vs. just invoking yield in an Enumerator.

The "Well-grounded Rubyist" suggests that one doesn't "yield from the block" but doesn't explain precisely what's going on.

Thanks

A: 

The Enumerator::Yielder#yield method and the Enumerator::Yielder::<< method are exactly the same. In fact, they are aliases.

So, which one of those two you use, is 100% personal preference, just like Enumerable#collect and Enumerable#map or Enumerable#inject and Enumerable#reduce.

Jörg W Mittag
Well, I'm not sure I care so much about what he "thinks" as I do about what's actually going on. Are they the same or not? In other words, ise = Enumerator.new do |y| y << 1 y << 2 y << 3endexactly the same ase = Enumerator do yield 1 yield 2 yield 3end
David
No, obviously they are not the same, since the second one isn't even valid Ruby.
Jörg W Mittag
+2  A: 

Well, unless I'm missing something, the method with yield simply doesn't work. Try it:

e = Enumerator.new do |y|
  y << 1
  y << 2
  y << 3
end

f = Enumerator.new do
  yield 1
  yield 2
  yield 3
end

e.each { |x| puts x }
f.each { |x| puts x }

Which produces this:

telemachus ~ $ ruby yield.rb 
1
2
3
yield.rb:13:in `block in <main>': no block given (yield) (LocalJumpError)
        from yield.rb:19:in `each'
        from yield.rb:19:in `each'
        from yield.rb:19:in `<main>

When he says (page 304) "you don't do this," he doesn't mean "it's not the best way to do it." He means, "that won't work."

Edit: You can, however, call yield explicitly this way:

e = Enumerator.new do |y|
  y.yield 1
  y.yield 2
  y.yield 3
end

If you find saying yield more explicit or clearer than <<, then do it that way.

Second edit: Looking at David's original post and Jorg's updated answer, I think that there was a confusion originally about the question. Jorg thought David was asking about the difference between Enumerator::Yielder#yield and Enumerator::Yielder::<<, but David wasn't sure what The Well Grounded Rubyist means when it says "don't write yield 1 etc." My answer applies to the question about The Well Grounded Rubyist. (When I looked this thread back over today, my answer looked odd in the light of other updates.)

Telemachus
Yes, I discovered that yield doesn't work 'cos there's no block. But it's still not clear to me what the "yielder" is doing. It looks like it is collecting all the calculated values so that it can regurgitate them later when you use the enumerator. If that's the case, then it seems like it would only be practical for "small" sequences....you wouldn't want to make an enumerator that stored 50 million items away.
David