From: "David A. Black" Date: 2010-09-07T20:22:18+09:00 Subject: Re: Enumerator#each return value is surprising Hi -- On Sat, 4 Sep 2010, Christopher Dicely wrote: > On Thu, Sep 2, 2010 at 7:57 PM, Ryan Davis wrote: > >> >> That said, I think the result is as it should be, as enumerators should be (in my mind at least) acting as stand-ins for >> the real thing, they should be substitutable with the real thing and wind up with the same result: > > I suppose when the enumerator is created with the default options, I > can sort of see that (or at least, see it as unlikely to be harmful.) > When its created with enum_for with an argument other than :each, > though, it seems to me like you end up with more possibility for > unexpected results. > > e.g., > > array = ["a","b","c"] > enum = array.enum_for(:each_with_index) > enum.each {} # => ["a","b","c"] > enum.to_a.each {} # => [["a", 0], ["b", 1], ["c", 2]] > > That is, even ignoring the implementation class, the sequence returned > by Enumerator#each isn't always the same sequence that the Enumerator > represents. This isn't like any other Enumerable in core Ruby. I'd say that the enumerator represents enumeration logic (i.e., the logic borrowed from its "host" method), rather than a particular sequence. So you get the following parallels: ruby-1.9.1-p378 > a = [1,2,3,4] => [1, 2, 3, 4] ruby-1.9.1-p378 > e = a.each_with_index => # ruby-1.9.1-p378 > a.each_with_index.to_a => [[1, 0], [2, 1], [3, 2], [4, 3]] ruby-1.9.1-p378 > e.to_a => [[1, 0], [2, 1], [3, 2], [4, 3]] ruby-1.9.1-p378 > a.each_with_index.each => # ruby-1.9.1-p378 > e.each => # # returns itself, since it's # already an enumerator ruby-1.9.1-p378 > a.each_with_index.each {} => [1, 2, 3, 4] ruby-1.9.1-p378 > e.each {} => [1, 2, 3, 4] In other words, the enumerator is behaving like a.each_with_index, not like a and not like itself.to_a. This isn't surprising, of course, since e is the return value from a.each_with_index :-) And I think it's consistent. In particular, note the last pair of examples, which both return the original array object. I guess I'm not sure how else it could work, since anything else would (I think) be a departure from the idea that the enumerator gets its each logic not just from a particular object but from an object/method combination. David -- David A. Black, Senior Developer, Cyrus Innovation Inc. The Ruby training with Black/Brown/McAnally Compleat Philadelphia, PA, October 1-2, 2010 Rubyist http://www.compleatrubyist.com