You are looking for doesNotUnderstand:
. If reduce
is an object that does not implement +
but you send it anyway, then instead its doesNotUnderstand:
method will be invoked. Normally it just raises an error. But you can override the default, and access the selector +
and the other argument and do whatever you like with them.
For simplicity, create a class Reduce
. On its class side, define the method:
doesNotUnderstand: aMessage
^aMessage argument reduce: aMessage selector
Then you can use it like this:
Reduce + (#(1 2 3) * #(4 5 6))
which in a Squeak workspace answers 32, as expected.
It works because *
is already implemented for Collections with suitable semantics.
Alternatively, add a class ApplyToAll
with this class-side method:
doesNotUnderstand: aMessage
^aMessage argument collect: [:e | e reduce: aMessage selector]
and also add this method to SequenceableCollection
:
transposed
^self first withIndexCollect: [:c :i | self collect: [:r | r at: i]]
Then you can write
Reduce + (ApplyToAll * #((1 2 3) #(4 5 6)) transposed)
which is pretty close to your original idea.