2

我正在尝试使用两个循环来反转堆栈,一个循环将数据堆栈中的项目发送到返回堆栈。另一个是让它们从返回堆栈到数据堆栈。不幸的是,它不起作用 & gforth 返回堆栈下溢错误。下面是代码:

: 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

4

2 回答 2

4

您在这里遇到的麻烦是DO ... LOOP将循环参数(索引和终止值)保留在返回堆栈上并在循环结束时丢弃它们。这就是为什么>R并且R> 必须在循环期间保持平衡。

您的代码在循环期间将一个值放在返回堆栈上,然后在循环结束时将其丢弃,留下一个杂散循环参数仍然存在,整个事情变得混乱。

你可以像这样得到你想要的结果......

: REVERSE ( i*x i -- i*y ) 0 DO I ROLL LOOP ;

......虽然我有点不明白你为什么想要!

编辑(在阅读评论和 ruvim 的回复后):

  1. 无论如何,您最初的反转堆栈算法都不会起作用,因为一系列R>s 将顺序反转到返回堆栈,并且相应>R的 s 再次将其反转回参数堆栈,使顺序保持原样。

  2. 类似于 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)与任何影响堆栈深度的东西一起使用DROPor DUP,但' 2* 4 APPLY工作得很好!

于 2020-02-01T08:12:22.060 回答
3

无需反转 N 个顶部堆栈项来为每个项应用一些操作。一个可能的解决方案如下。

: 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
于 2020-02-01T16:51:18.833 回答