Question

Is it possible to send an anonymous message to an object? I want to compose three objects like this (think FP):

 " find inner product "
 reduce + (applyToAll * (transpose #(1 2 3) #(4 5 6)))

where reduce, applyToAll and transpose are objects and +, * and the two arrays are arguments passed to anonymous messages sent to those objects. Is it possible to achieve the same using blocks? (but no explicit usage of value:).

OTHER TIPS

aRealObject reduceMethod: +; 
            applyToAll: *; 
            transpose: #(#(1 2 3) #(4 5 6));
            evaluate

would work when aRealObject has defined the right methods. Where do you need a block?

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top