1

y:=3。z:=4。
h:= '[x:= y+z.]'。
(BlockClosure readFromString: h) 值。

我有这段代码,我试图在 smalltalk 语法中获取一个字符串,并尝试将它放在一个块中并执行它,但是我收到一个错误,上面写着:
未处理的异常:消息不理解 #+

当我做类似
h:= '[x:= 3+4.]' 的事情时。
(BlockClosure readFromString: h) 值

它工作得很好。我不明白为什么会这样。我猜 y 没有指向任何东西,它不理解 + 方法。但是为什么该块不将 y 和 z 视为自由变量?

4

3 回答 3

4

您的问题是 y 和 z 在实际将字符串编译成块的上下文中是未知的。使用这样的东西可能会更好:

h := '[ :y :z | x := y + z]'.
(BlockClosure readFromString: h) value: 3 value: 4.

虽然我怀疑代码可能也不起作用 - 因为 x 没有在任何地方声明,所以更正确的版本是:

h := '[ :y :z | y + z]'.
x := (BlockClosure readFromString: h) value: 3 value: 4.

我不认为有任何真正的方法可以让块的字符串表示在它被解析的上下文中像真正的闭包一样,因为它无法访问变量 - 并且无法编译。

于 2013-10-25T04:06:49.660 回答
3

如果您真的需要这样做,请尝试以下操作:

   | x y z h block |
   y:=3. z:=4.
   h:= '[x:= y+z.]'.

   block := Compiler new
      evaluate: h
      in: thisContext
      allowReceiver: true
      receiver: self
      environment: self class environment
      notifying: nil
      ifFail: [self error: 'Failed to compile'].

   ^block value

但是,我建议您找到解决问题的更好方法。在运行方法的上下文中动态编译字符串非常棘手并且可能很脆弱。

于 2013-10-25T15:52:43.167 回答
1

James Robertson 最近在他的博客上发布了关于动态代码生成的文章。您可能会发现它很有用。

于 2013-12-27T18:32:03.957 回答