From: Robert Dober Date: 2009-06-23T08:15:18+09:00 Subject: Re: map shall not return an Enumerator ( was re guru help ) On Mon, Jun 22, 2009 at 9:36 PM, Brian Candler wrote: > Robert Dober wrote: >> I believe that the confusion arises from the fact that map returns an >> Enumerator and that just seems quite flawed at second thought (or is >> this third thought ;). >> >> Why the heck does map return an Enumerator? If I wanted that I surely >> would have called to_enum ! > > I agree that map and select returning an Enumerator, in the way they do > in 1.8.7/1.9, is pretty pointless. But if map without a block (and > select without a block etc) are not useful, but I don't think it helps > to overload them in the way you want either. I'd rather get an error > raised, as per 1.8.6. Reading your mail and David's I came to the same conclusion. I wonder what took me so long to name a method that sends a message to the elements of a collection #send_to_elements ? > > Aside: what's more interesting to me is "horizontal" execution of > enumerators - that is, passing each value along instead of building > intermediate arrays - and thus being able to run map/select on infinite > lists. See: > > http://redmine.ruby-lang.org/issues/show/708 > http://redmine.ruby-lang.org/issues/show/707 > > There's also an implementation of this in the facets library. > > In this case, if you write > >  infinite.map { |x| x*2 }.select { |x| x % 3 == 0 } ... > > then an Enumerator is returned at each stage of the chain. However you > still need to provide a block to map and a block to select, of course, > so it's not the same as #map without block returning an Enumerator. Right now I find it a little confusing to use Enumerators in that way. I prefer streams to implement lazy data structures, because map with a block should return an array (or hash, but no argument on this, I am with the majority on this one ;). The "the tail of a stream is always a stream" paradigm of streams makes things so easy to understand. Anyway if it be streams or enumerators, I am sure that the introduction to laziness into Ruby would bring great benefits to its already very concise programming style. I wonder however if streams are not more general? They are very easy to be treated as enumerables (as long as one respects the infinity constraint) or Enumerators. Can you do this with lazy Enumerators? fibs = cons_stream( 0 ){ cons_stream( 1 ){ add_streams(fibs, fibs.tail) } } if you are interested: http://ruby-smalltalk.blogspot.com/2009/01/streams-lazy-programs-for-lazy.html#streams_in_ruby or James' blog about High Order Ruby http://blog.grayproductions.net/categories/higherorder_ruby. Well I guess I got OT on my own thread LOL. Cheers Robert