Smalltalk中的函数对象(或执行没有`value:`的块)

时间:2010-11-08 06:45:12

标签: functional-programming smalltalk squeak pharo

是否可以向对象发送匿名消息?我想组合这样的三个对象(想想FP):

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

其中reduceapplyToAlltranspose是对象,+*,两个数组是传递给发送给这些对象的匿名消息的参数。是否有可能实现相同的使用块? (但没有明确使用value:)。

3 个答案:

答案 0 :(得分:5)

aRealObject reduceMethod: +; 
            applyToAll: *; 
            transpose: #(#(1 2 3) #(4 5 6));
            evaluate
当aRealObject定义了正确的方法时,

将起作用。你需要一个街区?

答案 1 :(得分:5)

答案 2 :(得分:3)

您正在寻找doesNotUnderstand:。如果reduce是一个未实现+的对象,但无论如何都要发送它,那么将调用其doesNotUnderstand:方法。通常它只会引发错误。但是你可以覆盖默认值,并访问选择器+和另一个参数,并用它们做任何你想做的事。

为简单起见,请创建一个类Reduce。在课堂上,定义方法:

doesNotUnderstand: aMessage
    ^aMessage argument reduce: aMessage selector

然后你可以像这样使用它:

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

在Squeak工作区中,按预期回答32。

它的工作原理是因为已经为具有合适语义的集合实现了*

或者,使用此类方法添加类ApplyToAll

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

并将此方法添加到SequenceableCollection

transposed
    ^self first withIndexCollect: [:c :i | self collect: [:r | r at: i]]

然后你可以写

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

这与你原来的想法非常接近。