Yukihiro Matsumoto wrote: > > |I should say, however, that I don't care for the name 'butfirst'. > > It's a traditional name (but slightly different behavior) inherited > from Logo. In Logo, butfirst is cdr in Lisp, which returns given list > with its first element removed. Well tradition helps, but I think I'd still prefer another name. > |I've got three alternatives to propose: > | > |1) How about 'skip' (or 'discard') instead, which would nicely support > |its use as an enumerator like this: > | > | c.skip(n).map {|x|...} # map all but the first n > | > |If you like this, I'd also propose 'only' (or 'limit'): > | > | c.only(n).map { |x| ...} # iterates no more than n elements from c > > We already have #first, that works in reverse of #butfirst. I am not > sure skip/only pair is better, especially when #only would work same > as #first. #first is not the reverse of #butfirst. first returns an array but butfirst is an iterator and just returns the collection it is called on. I think I share David Black's concern. He wrote: > Especially with the magic enumerators, it's going to be hard to tell > what's going on if the method names are too subtle. Some enumerable methods return arrays, some return enumerators, and it is beginning to get confusing. I made a little table of the methods I'm discussing here: Method block with block without block ------------------------------------------------------------------- butfirst iterates returns collection returns enumerator first not allowed not allowed returns array take selects returns array returns array drop selects returns array returns array grep iterates returns array returns array select selects returns array returns enumerator find selects returns element returns enumerator I have a couple of related thoughts about this. First, are you sure that you want methods like find and select to return enumerators when called without a block? Since the block is used for filtering elements rather than enumerating them, I don't really see the use case here. I think I'd prefer methods like these to require a block. If someone really wants to create an enumerator from them, they can use enum_for, of course. I'd suggest that only more traditional iterators should return enumerators when called without a block. Second, I wonder if it is possible to unify Array and Enumerator so that one behaves like the other. Then we could treat all methods as if they returned an array or an enumerator. If we add next and rewind methods to Array (which I think would be easy) then we can treat the return value of take, drop, select, reject, etc. as an enumerator. But an even nicer thing would be if Enumerators could act like lazily filled arrays. That is, if I have an enumerator e, but use it like an array, it calls to_a on itself internally and then dispatches to the array. With that change, you could modify Enumerable#grep, for example, so that it returns an enumerator instead of an array. If you never treat the result as an array, to_a never gets called, and you get pipe-like behavior that works with unbounded collections. David