From: Robert Klemme Date: 2005-07-13T16:40:51+09:00 Subject: Re: accessing index inside map Brian Candler wrote: >> Well, apparently we have differing opinions on this. Personally I >> find the Enumerator approach simpler as it does not clutter the >> original's class interface (introducing an optional parameter on >> each method doubles the number of legal invocations). :-) > > My own interpretation of "do the simplest" includes "don't introduce > any unnecessary abstractions". Arguably, the 'optional' parameter is > always > there; it just happens to default to :each. There are lots of similar > cases > in the Ruby standard library. > > The Enumerator stuff is new to me, since I'm still just using 1.8.2. It's in 1.8.2 and I think it's been around for some time, maybe even as far back as 1.7.*. > However, I find obj.to_enum(:each_with_index) confusing; after all, > obj is *already* enumerable. Well, to_enum is rather a shorthand for to_enumerator. There's also enum_for (as Nobu pointed out). > Making this more general, you might get > > obj.rename(:each=>:each_with_index).inject(0) {|sum,(a,i)| sum + > a*i} With this naming I'd rather associate that :each is renamed on the instance obj to :each_with_index and that this change is permanent. The to_xyz notation clearly indicates a conversion i.e. you expect to get a new isntance. > Creating an object just to say "call #each_with_index instead of > #each" > seems wasteful unless you plan to re-use it, given that you could > just call #each_with_index in the first place. It's not that uncommon in OO oriented languages to create temporary objects. For example command pattern has often this property: you create an instance, set all properties you need for processing, execute it, fetch the result and drop the instance again. This is a nice way of doing housekeeping for temporary state that is solely associated with the calculation. The overhead in this case is neglectible in the general case, i.e., an iteration that creates lots of new objects along the way. > However, perhaps 'to_enum' could be called something friendlier, e.g. > > obj.using(:each_with_index).inject(0) {|sum,(a,i)| sum + a*i} using for what? > In fact, even > > obj.enum(:each_with_index).inject(0) {|sum,(a,i)| sum + a*i} That reads better IMHO. > reads better to me, as it's not stressing the creation of an > intermediate object. to_foo looks like you are converting obj into > something completely different, rather than just adding a temporary > wrapper. Yeah, maybe. Anyway, this is far better than rename IMHO. > From the OP's question, then, it's a question of > > [1,2,3,4,5,6].map(:each_with_index) { |x,i| [2,5].include?(i) ? x : > x*2 } > > versus > > [1,2,3,4,5,6].enum(:each_with_index).map { |x,i| [2,5].include?(i) > ? x : x*2 } > > I still prefer the first :-) It's a mapping operation, applied > directly to > an Array. > >> Well, I think a vote is in order. Did you consider submitting this >> as RCR? > > I'm not familiar with the RCR process. It's fairly easy: you register, create your RCR (there are some helpful questions on the website) and submit it. Then you wait for comments. DAB> See http://www.rcrchive.net. > I just thought I'd wait and see what the list members (and Matz in > particular) thought. This idea seems sufficiently obvious that I guess > there's some reason why it has not been implemented already. Certainly also a good approach. The main advantage I see with RCR's is that there is a reference point and all the comments are tied together. Kind regards robert