使用循环反转数据堆栈
Reverse the data stack using loops
我正在尝试使用两个循环来反转堆栈,一个是将项目从数据堆栈发送到 return 堆栈。另一个是将它们从 return 堆栈获取到数据堆栈。
不幸的是,它不起作用 & gforth returns 堆栈下溢错误。
下面是代码:
: srev ( n n2 n3 n4 n5 -- n5 n4 n3 n2 n)
6 0 do >r loop
6 0 do r> loop ;
1 2 3 4 5 srev
你在这里遇到的麻烦是 DO ... LOOP
将循环参数(索引和终止值)保存在 return 堆栈中并在循环结束时丢弃它们。这就是为什么 >R
和 R>
必须 在循环中成对平衡。
你的代码在循环期间将一个值放在 return 堆栈上,然后在循环结束时将其丢弃,留下一个杂散的循环参数仍然存在,整个事情变得一团糟。
你可以这样得到你想要的结果...
: REVERSE ( i*x i -- i*y ) 0 DO I ROLL LOOP ;
...虽然我有点不明白你为什么要这么做!
编辑(阅读评论和 ruvim 的回复后):
你最初的逆向堆栈算法无论如何都行不通,因为一系列 R>
s 将顺序颠倒到 return 堆栈上,相应的 >R
s
将它再次反转回参数堆栈,保持原样。
替代方法,类似于 ruvim 但没有递归,在这里
: APPLY ( n*x xt n -- n*x' )
DUP 1- -ROT ( n*x n-1 xt n )
0 DO ( n*x n-1 xt )
2>R \ park n-1 xt on return stack
2R@ DROP ROLL \ bring next item to top
2R@ NIP EXECUTE \ apply the function to it
2R> \ clear junk off return stack for now
LOOP ( n*x n-1 xt )
2DROP
;
它不会(因为使用 ROLL
)影响堆栈深度的任何东西,如 DROP
或 DUP
,但 ' 2* 4 APPLY
工作得很好!
不需要将 N 个栈顶项目的每一个都反转为 apply some operation。可能的解决方案如下。
: apply-top ( i*x i xt -- j*x ) \ xt ( x -- k*x )
swap dup 0= if 2drop exit then ( ... x xt i )
rot >r 1- swap dup >r recurse ( R: x xt )
2r> execute
;
一些测试:
2 3 4 3 ' 2* apply-top ( 4 6 8 ) . . . \ 8 6 4
2 3 4 3 ' drop apply-top ( ) \ it just drops 3 top items
我正在尝试使用两个循环来反转堆栈,一个是将项目从数据堆栈发送到 return 堆栈。另一个是将它们从 return 堆栈获取到数据堆栈。 不幸的是,它不起作用 & gforth returns 堆栈下溢错误。 下面是代码:
: srev ( n n2 n3 n4 n5 -- n5 n4 n3 n2 n)
6 0 do >r loop
6 0 do r> loop ;
1 2 3 4 5 srev
你在这里遇到的麻烦是 DO ... LOOP
将循环参数(索引和终止值)保存在 return 堆栈中并在循环结束时丢弃它们。这就是为什么 >R
和 R>
必须 在循环中成对平衡。
你的代码在循环期间将一个值放在 return 堆栈上,然后在循环结束时将其丢弃,留下一个杂散的循环参数仍然存在,整个事情变得一团糟。
你可以这样得到你想要的结果...
: REVERSE ( i*x i -- i*y ) 0 DO I ROLL LOOP ;
...虽然我有点不明白你为什么要这么做!
编辑(阅读评论和 ruvim 的回复后):
你最初的逆向堆栈算法无论如何都行不通,因为一系列
R>
s 将顺序颠倒到 return 堆栈上,相应的>R
s 将它再次反转回参数堆栈,保持原样。替代方法,类似于 ruvim 但没有递归,在这里
: APPLY ( n*x xt n -- n*x' )
DUP 1- -ROT ( n*x n-1 xt n )
0 DO ( n*x n-1 xt )
2>R \ park n-1 xt on return stack
2R@ DROP ROLL \ bring next item to top
2R@ NIP EXECUTE \ apply the function to it
2R> \ clear junk off return stack for now
LOOP ( n*x n-1 xt )
2DROP
;
它不会(因为使用 ROLL
)影响堆栈深度的任何东西,如 DROP
或 DUP
,但 ' 2* 4 APPLY
工作得很好!
不需要将 N 个栈顶项目的每一个都反转为 apply some operation。可能的解决方案如下。
: apply-top ( i*x i xt -- j*x ) \ xt ( x -- k*x )
swap dup 0= if 2drop exit then ( ... x xt i )
rot >r 1- swap dup >r recurse ( R: x xt )
2r> execute
;
一些测试:
2 3 4 3 ' 2* apply-top ( 4 6 8 ) . . . \ 8 6 4
2 3 4 3 ' drop apply-top ( ) \ it just drops 3 top items