我发现
: x : y ;
是合法的(至少在 gforth 中),但我想不出这种构造的用例。
据我了解,执行x
开始重新定义y
,但在结束分号时抛出错误:
: y 42 ; ok
: x : y ; ok
x 43 ;
:3: unstructured
x 43 >>>;<<<
Backtrace:
$7FD8A0818988 throw
$7FD8A08284E0 c(abort")
$7FD8A0835600 def?
$7FD8A08218C0 ;-hook
有人能解释一下吗?
如果您不需要这个构造,您可以添加检查:
现在,要在定义内部使用,
:
您必须写入['] : execute
。如您所见,我们可以合法地
:
在定义内部使用它来进行此检查。此类用法的另一个示例是防止重新定义。请注意,
:
(冒号)在执行时会从输入缓冲区使用名称(请参阅解析文本符号)并将冒号系统留在堆栈上,而;
(分号)会从堆栈中使用这个冒号系统( colon-sys -- )
: 。如果分号在堆栈顶部没有看到冒号系统,它可能会抛出错误(并且它会在 Gforth 中抛出错误)。这实际上与堆栈深度无关,而是与数据类型检查有关。还要注意,当 Forth 文本解释器在编译定义时遇到标准词时
:
,它不会执行该词,而是编译它 — 因为该词是普通词。 上述 Colon 的实现是一个立即词,因此当 Forth 文本解释器在编译定义时遇到它时,它会执行它。: x : y ;
执行y
时不会重新定义。这是因为在运行时调用,而不是在编译时调用。当您输入时,会调用从输入流中解析名称的函数;在本例中就是如此。因此,会创建一个新的定义。x
x
:
x 43 ;
x
:
43
43
第二,在运行时
x
调用,将堆栈推送到堆栈。Gforth 有内部检查,以确保在进行定义时控制堆栈是平衡的。即,运行时的控制堆栈必须与运行时的深度相同。在您的示例中,首先调用,然后调用。由于推送了未弹出的内容,因此会注意到并发出警告。y
42
:
;
x
:
y
y
;