有没有比这更好的方法:
|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]
答案 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中做一些稍微不同的事情。)