1

有没有比这更好的方法:

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

?

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

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

现在我想在哪里检查AnotherThing 而不是checkSomethingElse。

或者:

[:oneParameter :anotherParameter | 
    oneParameter doSomethingWith: anotherParameter]

现在我想在哪里添加第三个参数并且:

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

3 回答 3

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.
于 2011-04-20T12:36:09.630 回答
2

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

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

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

aBlock := factory value: 3 value: 2.

评估aBlock答案5

于 2011-04-20T20:00:14.063 回答
2

将 Block 序列化为字符串并进行字符串操作虽然很方便,但如果您对 Block 的内容没有非常清楚的了解,也会非常危险。

听起来您希望能够操作块的 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 中编写了以上内容。我不知道 Opal 的状态,Pharo 的新编译器,所以也许你会在 Pharo 中做一些稍微不同的事情。)

于 2011-04-21T07:59:41.970 回答