修改闭包的内容

时间:2011-04-20 10:13:03

标签: smalltalk pharo

有没有比这更好的方法:

|aBlock|
aBlock := [3+2].
aBlock := Object readFrom: (a printString copyReplaceAll: '3' with: '2').

编辑这段代码只是一个例子,例如:

[:something | 
    something checkSomethingElse ifNil: 
        [whatever] 
    ifNotNil:
        [something getSomethingDone]]

现在我想检查另一个而不是checkSomethingElse。

或:

[:oneParameter :anotherParameter | 
    oneParameter doSomethingWith: anotherParameter]

现在我想添加第三个参数:

[:oneParameter :anotherParameter :yetAnotherParameter | 
    oneParameter doSomethingWith: anotherParameter and: yetAnotherParameter]

3 个答案:

答案 0 :(得分:2)

In Pharo:

| aBlock   x |

x := 1.

aBlock := [ x := x + 1].

Transcript show: aBlock value printString; cr.

x := 41.

Transcript show: aBlock value printString; cr.

答案 1 :(得分:2)

当然你可以使用反射来操作块,但最干净的解决方案是通过用另一个块包装它来动态绑定块中的值:

factory := [ :a :b | [ a + b ] ].

factory生成块,其中a和b绑定到不同的值:

aBlock := factory value: 3 value: 2.

评估aBlock个答案5

答案 2 :(得分:2)

将一个块序列化为一个字符串并进行字符串操作虽然方便,但如果您对块的内容不是很清楚,那么它也很危险。

听起来你希望能够操作块的AST - 给定一个块,解析它,更改结构(在这种情况下替换文字),然后编译更改的结构。为此,你可以这样做:

| aBlock ast |
aBlock := [3+2].
ast := aBlock decompile.
ast statements first receiver: (DecompilerConstructor new codeAnyLiteral: 4).
aBlock := (Compiler evaluate: ast printString) first.
aBlock value. "==> 6"

请注意,我们实际上并没有改变aBlock,而是创建了aBlock的变异副本

该原则更普遍适用:反编译块,执行操作(例如,通过消息发送链中途更改选择器),编译新的解析树。 (我不知道如何编译树直接,而不是评估打印出来的树,但我确信有办法。)

(警告:我已经在Squeak中写了上述内容。我不知道Pharo的新编译器Opal的播放状态,所以也许你会在Pharo中做一些稍微不同的事情。)

相关问题