From: Robert Klemme Date: 2003-07-24T18:52:40+09:00 Subject: Re: A different Version of Enumerable#inject "Sascha D�rdelmann" schrieb im Newsbeitrag news:a39cf4fe.0307240041.dd541f8@posting.google.com... > "Robert Klemme" wrote about: > [ inject with variable num args block ] > > My first thought was that inject is complex enough as it is and more > features might prevent me from using it. My second thought was: Why > restrict this feature to inject? Yeah, i've thought of this. In fact, map could "benefit" from this, too. > But I still see some problems, too. > I don't use inject very often. (Reason: I always have to look up which > argument of the block was the result of last steps and which one was > the next entry of my enumerable. More arguments won't help me there. > ;-) I think it would help you, because if you know that the number of block arguments can differ it's quite naturally that the first one is the one that carries the value through the iteration while the rest are the enum elements. > But I often need to do things between two steps of an iteration > (do:separatedBy: in Smalltalk) or do things with two adjacent entries > (pairsDo: in Smalltalk). The proposed inject serves the latter. do:separatedBy: would need a different implementation. Something like module Enumerable def doSeparatedBy(blockEach, &blockIntermediate) first = true last = nil each do |e| if first first = false else blockIntermediate.call( last, e ) end blockEach.call( e ) last = e end end end irb(main):031:0> a=%w{a b c d e} ["a", "b", "c", "d", "e"] irb(main):032:0> str="" "" irb(main):033:0> a.doSeparatedBy( proc{|e|str< str "a|b|c|d|e" irb(main):035:0> > As you see my problem is method naming. I tend to expect differently > named methods for different tasks and not one method or block doing > different jobs depending on the number of arguments. IMHO my proposed inject does not change behavior depending on the number of arguments. It always yields the carry value + n enumeration elements, where n>=0. Of course you can change the initial value as well as the number of block arguments to achieve such different things as counting, mapping and the others I have shown. But that's true even for Enumerable#each. The difference lies in the block and not in the implementation of inject. > IMO the first argument of inject is meant to carry the information > from the steps already done (e. g. a computational result) into the > next iteration step. Exactly. That property of the method doesn't change. > Each iteration step gets this information plus > the next entry of my collection. .... or the next entries. > The carried information could contain > all the needed informations about previous steps (e. g. a fifo-list > holding some entries). From this point of view inject does everything > I need. But it would be a lot of code to achieve what the new inject > could do in a single line. Now, is this pro or con? Sounds more like pro to me. > My suggestion would be to add methods like eachTupel or injectTupel > instead of changing inject. Yeah, this might be better. But then again, inject as it stands today is just a special case of the more general one, i.e., the sliding window has size 1. Thanks for commenting. robert