#reduce: aReduction
���� Are you saying that aReduction is an object from which
���� a dyadic block and an initial value can be derived?
���� That's going to confuse the heck out of Dolphin and Pharo
���� users (like me, for example).�� And in my copy of Pharo,
���� #reduce: calls #reduceLeft:, not #foldLeft:.
���� The sad thing about #reduceLeft: in Pharo is that in order
���� to provide extra generality I have no use for, it fails to
���� provide a fast path for the common case of a dyadic block.
reduceLeft: aBlock
�� aBlock argumentCount = 2 ifTrue: [
������ |r|
������ r := self first.
������ self from: 2 to: self last do: [:each |
���������� r := aBlock value: r value: each].
������ ^r].
������ ... everything else as before ...
Adding up a million floats takes half the time using the
fast path (67 msec vs 137 msec).�� Does your #reduce:
also perform "a completion action"?�� If so, it definitely
should not be named after #inject:into:.
At any rate, if it does something different, it should have
a different name, so #reduce: is no good.
#reduce:init:
�� There's a reason why #inject:into: puts the block argument
�� last.�� It works better to have "heavy" constituents on the
�� right in an English sentence, and it's easier to indent
�� blocks when they come last.
�� Which of the arguments here specifies the 'completion action'?
�� What does the 'completion action' do?�� (I can't tell from the name.)
I think the answer is clear:
* choose new intention-revealing names that do not clash.
If I have have understood your reduce: aReduction correctly,
a Reduction specifies
��- a binary operation (not necessarily associative)
��- a value which can be passed to that binary operation
which suggests that it represents a magma with identity.
By the way, it is not clear whether
��{x} reduce: <<ident. binop>>
answers x or binop value: ident value: x.
It's only when ident is an identity for binop that you
can say 'it doesn't matter'.��
I don't suppose you could bring yourself to call
aReduction aMagmaWithIdentity?
Had you considered
�� aMagmaWithIdentity reduce: aCollection
where the #reduce: method is now in your class so
can't *technically* clash with anything else?
All you really need from aCollection is #do: so
it could even be a stream.
MagmaWithIdentity
>> identity
>> combine:with:
>> reduce: anEnumerable
�������� |r|
�������� r := self identity.
�������� anEumerable do: [:each | r := self combine: r with: each].
�������� ^r
MagmaSansIdentity
>> combine:with:
>> reduce: anEnumerable
�������� |r f|
�������� f := r := nil.
�������� anEnumerable do: [:each |
������������ r := f ifNil: [f := self. each] ifNotNil: [self combine: r with: each]].
�������� f ifNil: [anEnumerable error: 'is empty'].
�������� ^r
��