我需要实现一个带有多个出口点的idefinite循环。 不幸的是,最明显的解决方案 - REPEAT - 具有多个WHILE的UNTIL在Gforth和swapforth 中都不起作用(当然下面示例中的循环可以用DO - LOOP实现。但是,该代码只是一个演示真正的问题与嵌入式系统中的硬件控制有关,所以循环确实必须是无限的):
: test1 ( step -- step count )
0
begin
over +
dup .
dup 20 < while
dup 13 = while
repeat
;
3 test1
在“思考四”中引用了摩尔的陈述:
很多时候使用条件来摆脱循环。那个特别 通过具有多个出口点的循环可以避免使用。这是 一个直播主题,因为有多个WHILE结构 poly-Forth但尚未渗透至'Forth '83。这是一种简单的方法 在同一个REPEAT中定义多个WHILE。 Dean Sanderson也是 [Forth,Inc。]发明了一种引入两个出口的新结构 指向DO LOOP。鉴于这种结构,您将获得更少的测试。
不幸的是我找不到Dean的解决方案。 是否有任何可移植的方法在Forth中的无限循环中实现多个出口点?
答案 0 :(得分:2)
经过一些实验,我创建了一个基于DO + LOOP的解决方案。 我不知道它是否与Dean Sanderson提出的相同。
我已经在Gforth和swapforth中成功测试过它。 似乎可以创建任意数量的退出点。 通过以下方式创建不定循环:0 1 DO循环内容此处0 + LOOP。 退出点由LEAVE创建,如果那么放置。
示例代码:
: test1 ( start step -- count step )
swap
1 0 do
over +
dup .
dup 20 > if
." >20 "
leave
then
dup 13 = if
." =13 "
leave
then
dup 17 = if
." =17 "
leave
then
0 +loop
;
测试结果:
> 1 3 test1
4 7 10 13 =13 ok
> 2 3 test1
5 8 11 14 17 =17 ok
> 0 3 test1
3 6 9 12 15 18 21 >20 ok
答案 1 :(得分:2)
EXIT
当然为定义提供了多个出口。您可以通过使用单独的单词或更整齐地使用引用来使循环的主体与定义相同:
: test ( start step -- count step )
swap [: begin
over + dup .
dup 20 > if ." >20" exit then
dup 13 = if ." =13" exit then
dup 17 = if ." =17" exit then
again ;] execute
( EXITs from loop continue here ) ;
答案 2 :(得分:1)
基于ruvim给出的评论,我已经测试了一个基于多个WHILE的解决方案,解决了额外的问题:
: test1 ( step start -- step count )
cr
begin
over +
dup . cr
dup 30 < while
dup 13 <> while
dup 17 <> while
repeat
." before 1st else" cr
else
." after 1st else" cr
then
." before 2nd else" cr
else
." after 2nd else" cr
then
;
确实有效。下面的测试显示了为了离开循环而执行的代码部分。
循环在第1次之后退出:
5 1 test1
6
11
16
21
26
31
after 2nd else
ok
循环在第二次之后退出:
5 3 test1
8
13
after 1st else
before 2nd else
ok
循环在第3次之后退出:
5 2 test1
7
12
17
before 1st else
before 2nd else
ok
因此,如果有人想将动作分配给每个WHILE,则应按如下方式进行:
: test1 ( step start -- step count )
cr
begin
over +
dup . cr
dup 30 < while
dup 13 <> while
dup 17 <> while
repeat
." exited after the 3rd while" cr
else
." exited after the 2nd while" cr
then
else
." exited after the 1st while" cr
then
;
有趣的是,上面如何扩展甚至更多的WHILE。 适用于4个WHILE的语法如下所示:
: test1 ( step start -- step count )
cr
begin
over +
dup . cr
dup 30 < while
dup 13 <> while
dup 17 <> while
dup 19 <> while
repeat
." exited after the 4th while" cr
else
." exited after the 3nd while" cr
then
else
." exited after the 2nd while" cr
then
else
." exited after the 1st while" cr
then
;
以上代码在Gforth和swapforth都经过测试。 有趣的问题是不同可能解决方案中的返回堆栈占用率。 (例如,在J1B CPU中,返回堆栈深度仅为32级)。