“Sascha Dördelmann” wsdng@onlinehome.de schrieb im Newsbeitrag
news:a39cf4fe.0307240041.dd541f8@posting.google.com…
“Robert Klemme” bob.news@gmx.net 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<<e} ) {str<<“|”}
[“a”, “b”, “c”, “d”, “e”]
irb(main):034:0> 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