Function objects in Smalltalk (or executing blocks without a value: `)

Can I send an anonymous message to an object? I want to create three such objects (think FP):

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

where reduce , applyToAll and transpose are objects and + , * , and two arrays are arguments passed to anonymous messages sent to these objects. Is it possible to achieve the same use of blocks? (but without explicitly using value: .

+6
functional-programming smalltalk squeak pharo
source share
3 answers
 aRealObject reduceMethod: +; applyToAll: *; transpose: #(#(1 2 3) #(4 5 6)); evaluate 

will work when aRealObject has defined the correct methods. Where do you need a block?

+5
source share

You are looking for doesNotUnderstand: If reduce is an object that does not implement + , but you send it anyway, then its doesNotUnderstand: method will be called instead. This usually just causes an error. But you can override the default value and access the + selector and another argument and do whatever you like with them.

For simplicity, create a reduce class. On the class side, define a method:

 doesNotUnderstand: aMessage ^aMessage argument reduce: aMessage selector 

Then you can use it as follows:

 Reduce + (#(1 2 3) * #(4 5 6)) 

which in the Squeak workspace answers 32, as expected.

This works because * already implemented for collections with suitable semantics.

Alternatively, add the ApplyToAll class using this class method:

 doesNotUnderstand: aMessage ^aMessage argument collect: [:e | e reduce: aMessage selector] 

and also add this method to the 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 close to your original idea.

+3
source share

All Articles