From: "David A. Black" Date: 2009-06-23T10:32:42+09:00 Subject: Re: map shall not return an Enumerator ( was re guru help ) Hi -- On Tue, 23 Jun 2009, Robert Dober wrote: > 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 ? I'm not sure what that buys you, though. There's already #map and #send, and between those can't you easily do all of this? > 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) } } I can't do it that compactly (though maybe someone can). Here's some doodling with the block form of an enumerator: fib = Enumerator.new do |y| # y is a "yielder" object -- lazy yielding via << y << 1 a,b = 0,1 loop do y << a + b a,b = b, a + b end end p fib.next p fib.next p fib.next p fib.next p fib.next # Output: 1 1 2 3 5 Or maybe something using cycle. David -- David A. Black / Ruby Power and Light, LLC Ruby/Rails consulting & training: http://www.rubypal.com Now available: The Well-Grounded Rubyist (http://manning.com/black2) "Ruby 1.9: What You Need To Know" Envycasts with David A. Black http://www.envycasts.com