Обратный стек данных с использованием циклов - PullRequest
2 голосов
/ 01 февраля 2020

Я пытаюсь перевернуть стек, используя два цикла, один для отправки элементов из стека данных, чтобы вернуть стек. И другой, чтобы получить их из стека возврата в стек данных. К сожалению, это не работает & 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

Ответы [ 2 ]

4 голосов
/ 01 февраля 2020

Проблема, с которой вы столкнулись, состоит в том, что DO ... LOOP сохраняет параметры l oop (индекс и значение завершения) в стеке возврата и отбрасывает их в конце l oop. Вот почему >R и R> должны быть сбалансированными парами в течение всего oop.

Ваш код помещает значение в стек возврата в течение l oop, что затем сбрасывается в конце l oop, оставляя безразличный параметр l oop все еще там, и все становится бесполезным.

Вы можете получить желаемый результат, как этот ...

: 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) со всем, что влияет на глубину стека, например DROP или DUP, но ' 2* 4 APPLY работает просто отлично!

3 голосов
/ 01 февраля 2020

Нет необходимости переворачивать 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
...