是否可以向对象发送匿名消息?我想像这样组成三个对象(想想 FP):
" find inner product "
reduce + (applyToAll * (transpose #(1 2 3) #(4 5 6)))
其中reduce
,applyToAll
和transpose
是对象 和+
,*
两个数组是传递给发送到这些对象的匿名消息的参数。是否可以使用块来实现相同的目标?(但没有明确使用value:
)。
是否可以向对象发送匿名消息?我想像这样组成三个对象(想想 FP):
" find inner product "
reduce + (applyToAll * (transpose #(1 2 3) #(4 5 6)))
其中reduce
,applyToAll
和transpose
是对象 和+
,*
两个数组是传递给发送到这些对象的匿名消息的参数。是否可以使用块来实现相同的目标?(但没有明确使用value:
)。
aRealObject reduceMethod: +;
applyToAll: *;
transpose: #(#(1 2 3) #(4 5 6));
evaluate
当 aRealObject 定义了正确的方法时会起作用。你在哪里需要一个块?
也许您真正想做的是在 Smalltalk 中定义一个 DSL?
您正在寻找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)
这与您最初的想法非常接近。