我不太确定变量范围在 Io 中的作用。文档说它有闭包,但我似乎无法在idx
和next
方法中看到prev
。父可见性是关闭的关键前提,那么它们如何工作?
List iterator := method(
idx := 0
itr := Object clone
itr next := method(
idx = idx + 1
return self at(idx)
)
itr prev := method(
idx = idx - 1
return self at(idx)
)
return itr
)
应该如何实现?
答案 0 :(得分:7)
所以你从根本上误解了方法和块的工作方式,但没关系。让我们回顾一下基础知识:
context表示本地对象,基本上是堆栈帧。范围意味着在调用块/方法时谁将成为块激活的“发送者”。您可以通过方法或块上下文中的call sender
对象来访问它。
现在,让我们来看看你的代码。它几乎是完美的,只有一件事缺失,而且不明显。
由于方法具有动态范围,因此它们的scope
消息返回nil。这表示评估者应该将接收到该消息的任何对象作为发送上下文传递。我们不希望这种行为,我们希望捕获一些范围,特别是我们定义的iter
方法的本地化。让我们看一个更正的例子:
List iterator := method(
idx := 0
itr := Object clone
itr next := method(
idx = idx + 1
at(idx)
) setScope(thisContext)
itr prev := method(
idx = idx - 1
at(idx)
) setScope(thisContext)
itr
)
我简化了机构,但它们在功能方面没有改变(除少数消息发送外)。重要的是在分配给setScope
/ next
之前传递给方法的prev
调用。我本可以选择将其重写为:
iter prev := block(
idx = idx - 1
at(idx)
) setIsActivatable(true)
但是我必须让块可激活,因为默认情况下块不可激活。上面的代码和使用itr prev
的更正method()
在功能上是等效的。
方法不是闭包,块是。块只是一个范围非零的方法,它们是同一个对象。