块的内部是否可以知道它接收到的选择器并据此评估自己?

Can the inside of a block be aware of the selector it received and evaluate itself based on that?

假设我们在代码中的某个地方有一个块,我们将它分配给一个变量(实例或本地),就像这样。

someName := [ anInstanceVariable doThis. anotherInstanceVariable doThat.] 

从外部我想这样使用它:

someName someMessageTheBlockDoesntImplement: argument.

块是否可以作用于特定选择器 someName 并让 anInstanceVariableanotherInstanceVariable 分别执行它和 return 这些对象?

PS。它将充当某种转发器。

您始终可以通过以下方式实现 BlockClosure class 的 doesNotUnderstand:

doesNotUnderstand: aMessage
    ^ self value: aMessage selector value: aMessage arguments  

然后你必须有这样的块:

[ :selector :args |
    ^ { anInstanceVariable      perform: selector withArguments: args.
        anotherInstanceVariable perform: selector withArguments: args } ]

但你为什么要做那样的事情?

所有 Smalltalk 方言都允许通过某种方式访问​​当前上下文。在 VisualWorks 和 Pharo 中,您使用#thisContext。所以如果你有这样的方法......

Object>>someMethod
    ^[thisContext sender inspect] value

...发送评估:'abc' someMethod ...你会得到一个MethodContext --> ByteString(Object)>>someMethod

或者……

Object>>someMethod: aBlock
    ^aBlock value

'abc' someMethod: [thisContext sender inspect]

--> 字节串(对象)>>someMethod:

如果您需要查看更多堆栈,您可以使用类似...

| context frames | 
context := thisContext.
frames := OrderedCollection new.
[context isNil or: [context stack isNil]] whileFalse: [
    frames add: context.
    context := context sender].
^frames

在 VA Smalltalk 中,您可以编写...

someMethod
    ^[Processor activeProcess currentFrame context inspect] value

...一个 BlockContextTemplate --> [] in Object>>#someMethod

查看调试器代码是了解您可以使用哪些其他技术的好方法。

这个问题相当混乱。首先,我猜你的意思是 "the selector someMessageTheBlockDoesntImplement:" 而不是 "someName"。但是你基本上要求的是能够制作转发代理。

您通常不使用 BlockClosures 来执行此操作,而是创建一个 class MyForwarder,它继承 Object 甚至 ProtoObject(取决于您使用的 Smalltalk 以及您希望转发器的透明度)。

在此 class 中添加您的两个实例变量,以便您可以保存它们和一些方法,以便您可以设置它们等。

然后你在 MyForward 中实现 #doesNotUnderstand: 看起来像这样:

doesNotUnderstand: aMessage
    aMessage selector == #thisMessageGoesToFirstGuy
        ifTrue: [
             ^ firstGuy perform: aMessage selector withArguments: aMessage arguments ] 
        ifFalse: [
             ^ secondGuy perform: aMessage selector withArguments: aMessage arguments ] 

代码未经测试,但您明白了。