2 votes

Inverser la pile de données à l'aide de boucles

J'essaie d'inverser la pile en utilisant deux boucles, l'une pour envoyer des éléments de la pile de données à la pile de retour. Et une autre pour les récupérer de la pile de retour à la pile de données. Malheureusement, cela ne fonctionne pas et gforth renvoie l'erreur "stack underflow". Voici le code :

: 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

4voto

phisheep Points 72

Le problème, c'est que DO ... LOOP conserve les paramètres de la boucle (index et valeur de terminaison) sur la pile de retour et les rejette à la fin de la boucle. C'est pourquoi >R y R> debe être en paires équilibrées au cours d'une boucle.

Votre code place une valeur sur la pile de retour pendant la boucle, qui est ensuite rejetée à la fin de la boucle, laissant un paramètre de boucle égaré encore là, et le tout devient détraqué.

Vous pouvez obtenir le résultat que vous souhaitez comme ceci ...

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

... bien que je sois un peu perplexe quant à la raison pour laquelle vous voudriez le faire !

EDIT (après lecture des commentaires et de la réponse de ruvim) :

  1. Votre algorithme initial d'inversion de la pile n'aurait de toute façon pas fonctionné, car une série de R> inverse l'ordre sur la pile de retour, et la commande >R s l'inverse à nouveau sur la pile de paramètres en laissant l'ordre tel qu'il était.

  2. Une autre approche, similaire à celle de ruvim mais sans récursivité, est la suivante

    : 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
    ;

Cela ne fonctionnera pas (à cause de l'utilisation de ROLL ) avec tout ce qui affecte la profondeur de la pile comme DROP o DUP mais ' 2* 4 APPLY fonctionne parfaitement !

3voto

ruvim Points 78

Il n'est pas nécessaire d'inverser les éléments de la pile supérieure N pour appliquer une opération pour chacun d'entre eux. Une solution possible est la suivante.

: 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
;

Quelques tests :

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X