知道为什么以下不起作用吗?(R3)
o: make object! [
foo: does [do "bar"]
bar: does [print "hello from bar"]
]
o/foo
** Script error: bar has no value
** Where: catch either -apply- do foo
** Near: catch/quit either var [[do/next data var]] [data]
试试这个:
o: make object! [
foo: does [do get bind load "bar" self]
bar: does [print "hello from bar"]
]
o/foo ;this will work
你需要那个 BINDing 因为你的“栏”存在于对象中,而不是全局范围内。
也检查一下:
my-func: does [print "ok"]
o: make object! [
foo: does [do "my-func"]
bar: does [print "hello from bar"]
]
o/foo ;this will work too
您需要加载它,因为它是一个字符串,但它必须是一个要绑定的单词。所以这些也可以工作(把它们放在你的对象中):
do get bind to-word "bar" self
或者
do get bind 'bar self
之所以“self/bar”不知道在哪里可以找到 'BAR 是因为Rebol 中没有范围(至少在传统的 CS 含义中没有)。
Rebol 中的单词只有在静态绑定到上下文后才有意义。当你“制作一个对象”时,这种情况会自动发生,所以很多人甚至在使用多年后都没有意识到这一点。
它提取其规范中的所有根集词(在本例中为 [FOO: BAR:] )
将它们添加到其当前的内部单词中(SELF:默认情况下,如果您使用对象作为基础,则更多)
然后将块中的所有单词(分层)绑定到它添加到其规范中的那些集合词。
执行块。
所以你看,一旦你执行块为时已晚,单词已经被分配了它们的含义,这允许解释器询问它们的值(这可能会触发表达式评估,因此是 REBOL 中的 E)。
DO 和 LOAD 不能自动绑定到除了全局上下文之外的任何东西......因为没有像传统 OOP 和命令式语言那样的“当前上下文”这样的东西(请记住,没有范围)。确实,一旦执行,该信息将不再存在,除非您将“当前”上下文绑定到一个单词……这就是 'SELF 所做的,但要绑定它必须已经加载,执行时一个字符串,从未发生过。
最后我要补充一点,乍一看可能并不明显,但是当它绑定 Object spec 块时,它仍然不知道 FOO 和 BAR 到底是什么。事实上,FOO 和 BAR 可以访问 'O 对象的唯一方法是因为它们的功能块,当它通过 'MAKE 运行时,被绑定到对象......是的,甚至在它知道它是一个函数之前。那么如果函数定义了自己的局部变量,它会将其主体块重新绑定到那些新的局部变量......因为你猜对了......函数创建自己的内部上下文,它得到相同的 MAKE 处理(但没有内部 SELF单词)。
我希望这有助于以更明显的方式澄清事情。
这是代码没有作用域的证明:
a: make object! [
data: "HAHAHAAAAA!!!"
action: does [print self/data]
]
b: make object! [
data: "BUMBLING BEHEMOT"
action: does [print self/data]
]
b/action: get in a 'action
; this will print HAHAHAAAAA!!!
b/action
要进一步解释 moliad 的答案,请参阅以下说明:
REBOL 单词带有对其上下文的引用。不同的不是在哪里评估一个词,而是在哪里声明它。
来自http://blog.revolucent.net/2009/07/deep-rebol-bindology.html
这是一个很好的例子:
x: 0
b: [] loop 3 [use [x] [x: random 100 append b 'x]]
;== [x x x] <-- there are three X which looks same words (and they are same actually)
reduce b
;== [95 52 80] <-- but they have different values in their contexts
probe x
;== 0 <-- in global context, it has another value as well
乍一看,这看起来很奇怪,但实际上并非如此。USE 每次在 LOOP 中创建一个新的上下文,我们将 X(在 USE 创建的上下文中)设置为一个值,然后将 WORD(不是该值!)附加到一个块中。我们附加到块中的所有单词都带有它们自己的上下文,但它们看起来是同一个单词。
当我们减少(或打印等)时,当我们在自己的上下文中获取它们的值时,我们会看到它们都有不同的值!