我一直在努力理解它,所以我写了一个简单的词来测试它:
: test ." compile time" DOES> ." runtime" ;
问题是,这个词的表现方式根本不一致。它的输出似乎取决于许多因素,如:
- 这是要解释的第一行吗
- 在它之后还有其他词定义吗
此外,有时它根本不打印任何内容。
(使用Gforth(
这是您的代码:
: test ." compile time" DOES> ." runtime" ;
输入后,我可以使用你的单词,而不必你遇到的模糊行为:
CREATE def 12345 , test prints "compile time"
它打印compile time
,因为这是在DOES>
之前编译到test
中的行为。注意:这实际上并不是在编译时运行的
DOES>
结束单词的定义,但对其进行更改,使test
也修改最后定义的单词,使其将数据字段地址放在堆栈上,然后运行在DOES>
之后找到的行为。
使用我创建的单词,它具有您定义的实例化行为,遵循推送地址的隐含行为:
def @ . prints runtime 12345
Forth 2012注:根据Forth 2012中DOES>
的定义,如果最后一个词没有用CREATE
定义,这将导致歧义行为。然而,Gforth允许修改任何单词的定义
我希望这个例子有助于解释为什么通常在使用DOES>
的定义中使用CREATE
,但它肯定不是必需的。
ruvim的答案在Gforth中可能更容易理解。
下面的代码定义了一个"经典"定义词,该词在编译时创建初始化为堆栈上的项的变量。我希望定义中的跟踪语句将有助于显示正在发生的事情
: var create: n <name> -- ; does>: -- addr ; initialised VARIABLE
create create a dictionary item for <name>.
." HERE at compile time: " HERE .
, place n at HERE in the dictionary
does> Push the HERE as at compile time to the stack
." Run time address on the stack:" dup .
;
CCD_ 11现在可以用于定义具有在DOS>之后定义的运行时动作的新词;。
10 var init10 Use var to define a new word init10
HERE at compile time: 135007328
init10 CR DUP . @ .
Run time address on the stack:135007328
135007328 10 addr of init10, content of that address.
12 var init12 Use var to define a new word init12
HERE at compile time: 135007376
init12 CR DUP . @ .
Run time address on the stack:135007376
135007376 12
100 init10 ! Store 100 in init10
Run time address on the stack:135007328
init10 @ .
Run time address on the stack:135007328 100
init10 now contains 100
希望这些答案将提供一个框架来探索DOS>的定义词和动作;。
互动播放
在Gforth中,您可以对does>
进行解说。
create foo 123 ,
foo @ . prints 123
does> ( addr -- ) @ . ;
foo prints 123
does> ( addr -- ) @ 1+ . ;
foo prints 124
' foo >body @ . prints 123
因此,当最后一个单词通过create
定义时,does>
只是改变了最后一个词的行为。如果在最后一个单词未通过create
定义的情况下运行does>
,这是一个错误。
实践中的使用
通常,CCD_ 17仅用于为通过CCD_ 18定义的单词设置一次新行为。多次改变这种行为的能力只是历史实施的副作用,而这种影响几乎没有在实践中使用。
替代方式
在实践中,使用does>
的情况也可以在没有does>
的情况下实现。
例如,让我们想要实现一个字counter
,它创建一个计数器,每次返回下一个值,并以以下方式使用:
1 counter x1
x1 . prints 1
x1 . prints 2
x1 . prints 3
通过create
does>
实现
: counter ( x0 "ccc" -- ) Run-Time: ( -- x )
create , does> ( addr -- x ) dup >r @ dup 1+ r> !
;
使用报价的实现
[undefined] lit, [if] : lit, ( x -- ) postpone lit, ; [then]
[undefined] xt, [if] : xt, ( xt -- ) compile, ; [then]
: counter ( x0 "ccc" -- ) Run-Time: ( -- x )
align here >r , [: ( addr -- x ) dup >r @ dup 1+ r> ! ;] >r
: r> r> lit, xt, postpone ;
;
通过单词]]
:使用宏(代码内联(的实现
: counter ( x0 "ccc" -- ) Run-Time: ( -- x )
align here >r ,
: r> lit, ]] dup >r @ dup 1+ r> ! [[ postpone ;
;
定义分配内存的单词的单词可以通过DOS>其将地址提供给存储器块。
一个简单的例子是CONSTANT,它可以定义为
:常量(n--(创建,确实>@;