Le RPL. (Texte d'HP mâd)
Le RPL ou LISP Polonais Inversé est un langage développé pour la
HP28 puis adapté à la HP48. Ce langage basé sur le jonglage avec des
types abstraits de données ou objets est d'une puissance et d'une
simplicité inégalées .
Le principe de base du RPL est très simple. Il consiste à
l'automatisation de tâches à taper au clavier.Prenons comme exemple
une suite d'instructions destinées à incrémenter le nombre au niveau 1
de la pile. "1 +". Le programme réalisant la même opération sera tout
simplement « 1 + ». Il suffit de spécifier que c'est un programme et
le tour est joué .
Je vais donc tout simplement me borner à vous donner la 'liste' des
instructions RPL spécifiques à la programmation (et évidement vous
apprendre comment vous en servir). Pour ce qui est des instructions
'classiques', je me bornerai à vous renvoyer à l'annexe G de votre
manuel d'utilisation où vous trouverez la liste des instructions RPL
classiques.
Parmi les instructions que je vais vous expliquer, il en existe 2 sor
s appelés 'Structures de contrôle'. Tant que vous ne les maitrisez
pas, inutile d'essayer de programmer en assembleur, ou en external,
car ces structures constituent la BASE de la programmation.
Comment entrer un programme.
Bon, alors, gros naze! Pour allumer ta HP, tu appuies avec ton
indexe droit sur la touche en bas à gauche portant l'inscription
ON.
Ensuite tu appuies sur la touche Shift Lavande (orange pour
SX) qui se trouve deux touches au-dessus du ON, puis sur la touche-.
tu te retrouves avec les symboles et le curseur qui clignote. Tu
peux alors taper ton programme.
«
»
Les instructions de tests
Je parlerai beaucoup de programmes sortant un 0 ou un réel
>1. Voici ceux qui sont implémentés en machineIl existe plusieurs
tests sur HP:
Le diffèrent # Shift bleu 1
L'égal == Shift rouge 1
L'inférieur
Le supérieur > Shift bleu 2
L'inférieur ou égal <= Shift rouge 3
Le supérieur ou égal >= Shift bleu 3
qui réalisent un test sur des objets comparables (réels,
binaires). les == et différents s'appliquent sur tout objet et testent
s'ils sont pareils.
On peut aussi utiliser les opérations logiques sur les 0 et le 1:
AND, OR, XOR et NOT afin de réaliser le test voulu.
Il faut noter aussi que beaucoup d'instructions renvoient un 0 ou
autre chose, par exemple POS qui renvoie la position, ou un 0, ce qui
évite des tests inutiles en sortie. Par exemple exécuter toto si la
chaîne contient la sous-chaine.
IF
"AA" POS
THEN
toto
END
Les boucles.
Le boucles sont des structures de contrôle qui permettent de
répéter une action, soit un certain nombre de fois, soit jusqu'à un
événement, soit tant que certaines conditions sont remplies.
Il existe trois sortes de boucles qui servent dans des cas
différents.
La boucle FOR
Généralités
La boucle FOR s'applique dans les cas où l'on doit faire v
ier un indice d'une valeur de départ à une valeur de fin connue à
l'avance. Par exemple, si on cherche le plus grand élément d'un
tableau, on devra 'scanner' tous les éléments du tableau (il y en à
évidemment N), donc on aura besoin d'une variable qui prendra
successivement toutes les valeurs de 1 à N.
En RLP, la syntaxe du FOR est la suivante:
2: Indice de départ @ Un réel
1: Indice de fin @ Un autre réel
FOR Variable @ Ici, on indique le nom de la variable
Instructions à répéter
NEXT
Exemple de programme: Afficher les
entiers de 1 à 500
1 500 @ On boucle de 1 à 500
FOR a @ La variable qui sert de compteur est a
a@ On met le contenu de a sur la pile
1 DISP @ L'instruction DISP affiche l'objet du niveau 2 de la pile à la ligne donnée par le réel au niveau 1
NEXT @ Et la fin de boucle
1e extension du FOR
Le STEP en pas constant (avant ou arrière)
Dans certains cas, on peut désirer boucler, non p
de 1 vers 500, mais de 500 vers 1 (parcourir les indices à
l'envers). Ceci est évidement possible grâce à l'instruction
STEP. Cette instruction remplace le NEXT. Si nous analysons le NEXT,
que fait-il exactement? Il incrémente la variable, et si elle est
inférieur à l'indice de fin, il reéxécute les instructions de la
boucle.
Le STEP, va permettre d'incrémenter la variable d'une autre valeur que 1. Par exemple: '2 STEP' fera: Variable = Variable + 2 ....
Donc en faisant
500
1
FOR a
-1 STEP
On boucle de 500 à 1, donc à reculons.
on peut aussi faire la somme des 100 premiers nombres impairs .
0 @ au début, la somme est nulle
1 @ on boucle de 1
201 @ à 201
FOR a
@ boucle sur a
a @ mise de a sur la pile
+ @ ajout de a à la somme
2 STEP @ et on STEP
Le STEP en pas variable
Autre intérêt du STEP, le pas peut être donné par un programme. Imaginons un programme d'étude de fonction et la fonction suivante:
Cette fonction peut se diviser en 3 zones: 2 zones où elle est très
complexe, où elle varie beaucoup et une 3e où elle est presque droite.
Si je fais un programme destiné à étudier cette fonction en
plusieurs points, je n'ai pas besoin de l'étudier sur des intervalles
aussi petits dans la zone 2 que dans les zones 1 et 3. Comme je fais
mon étude sur les points qui sont donnés par l'indice d'une boucle
FOR, je peux concevoir une petite routine qui calculera le pas entre
une itération et la suivante (par exemple avec un calcul de la dérivée
en ce point).
Ce qui donne
0 50 @ J'étudie ma fonction sur
@ l'interval 0 50
FOR a @ Boucle
Etude de la fonction en a
Calcul du pas pour l'étude suivante
STEP @ et le STEP dont la valeur est donnée par le calcul du dessus
2e extension du FOR: Le START
Il se peut que l'on n'ait pas
soin d'indice de bouclage; par exemple si l'on veut faire 50 fois un
calcul de probabilité pour vérifier l'exactitude de notre estimation ;
on n'a pas besoin d'un indice, on veut juste faire le calcul 50 fois;
le START est tout indiqué, il fonctionne exactement comme le FOR sauf
qu'il n'y a pas d'indice.
1 50
START @ Je boucle 50 fois
Calcul
NEXT
On peut évidemment faire un START STEP, mais cela ne sert
strictement à rien car le seul intérêt du STEP est de modifier
l'indice.
La boucle While
Je ne m'étendrai pas sur cette
boucle 102 ans, elle est toute simple. On l'utilise dans les cas où on
doit traduire une structure du type: Tant que ceci, Fais cela. Par
exemple, si j'ai devant moi pleins de filles à la queue leu leu, Tant
que la fille en premier a les yeux bleus, je passe à la
suivante.
C'est-à-dire sur HP
WHILE
a les yeux bleus
REPEAT
On passe à la suivante
END
Le programme qui remplacera le "a les
eux bleus" devra laisser sur la pile un réel soit nul: elle n'a pas
les yeux bleus, ou un réel supérieur a 1: elle a les yeux
bleus.
Autre exemple
WHILE
maman dit: "tu n'iras pas au cinéma"
REPEAT
"Maman je veux aller au cinéma voir
ROCKY V "
END
La boucle DO
Je ne m'étendrai pas sur cette boucle 102 ans , elle est
toutes simple aussi. on l'utilise dans les cas où on doit traduire une
structure du type: Je fais ça jusqu'à ce que ceci. Par exemple je tape
sur le type en face jusqu'à ce que j'ai mal aux
mains.
C'est-à-dire sur HP
DO
Tape sur le mec
UNTIL
J'ai mal aux mains
END
Le programme qui remplacera le "j'ai mal aux mains" devra laisser sur la
pile un réel soit nul: "j'ai pas mal aux mains", ou un réel supérieur
a 1: "Putain, ça fait mal!!!!".
Autre exemple
DO
Range une chose de ta chambre
UNTIL
Ta chambre est rangée
END
Différences fondam tales entre le While et le DO.
La différence est très simple,
dans le While, on teste d'abord où on met les pieds "While y a pas de
merde devant moi REPEAT j'avance END", alors qu'avec un DO, je mets le
pied dedans.
Evidemment, mes exemples sont excessifs, mais il
sont très démonstratifs et amusants!!
Les Tests
Le IF THEN ELSE standard
La structure de tests et le IF THEN ELSE END. C'est-à-dire: Si cela, alors toto, sinon titi.
sur HP cela donne
IF
Test @ Ce programme doit renvoyer un
@ 0 ou un réel > 1
THEN
Programme si test vrai
ELSE
Programme si test faux
END
exemple
IF
A 1 ==
THEN
"A=1" 1 DISP
ELSE
"A diffèrent de 1" 1 DISP
END
le ELSE est optionnel, on peut faire
juste
IF
A B ==
THEN
A 1 DISP
END
Le IFERR.
Sur la HP , il existe une instruction fort pratique et fort dégeulasse permettant de tester si
n programme conduit à une erreur. C'est le
IFERR
IFERR
Programme
THEN
Action à
exécuter en cas d'erreur
ELSE
Action à exécuter si pas
d'erreur
END
Comme je l'ai clairement indiqué, il
permet d'affecter une action à une erreur survenue dans un programme
donné.
Exemple
IFERR
/
THEN
"On ne
peut diviser par 0" 1 DISP
END
Le
Case.
Cette structure permet d'effectuer une action spécifique
pour chaque possibilité que peut prendre une
variable.
CASE
DUP 1 ==
THEN
DROP "A=1" 1 DISP
END
DUP 2 ==
THEN
DROP "A=2" 1 DISP
END
DUP 3 ==
THEN
DROP "A=3" 1 DISP
END
DUP 4 ==
THEN
DROP "A=4" 1 DISP
END
DROP
"A n'est pas égal à 1,
2,3 ou 4" 1 DISP
END
On remarque une cause de
défaut à la fin (a différent de ...).
Cette structure peut
paraître excellente, mais on fait plus rapide.
Les IFT, IFTE et S ed Case
Structure IFT et IFTE
Ces instructions
permettent les mêmes chose que les IF THEN ELSE END, mais elles sont
utilisables dans les expressions 'algebraic' et sont plus rapides. De
plus, elles correspondent plus à la notion de pile.
Structure du IFTE
3: Résultat d'un test
2: « Programme à exécuter si vrai
»
1: « Programme à exécuter si faux »
IFTE
Structure du IFT
2: Résultat d'un test
1: « Programme à
exécuter si vrai »
IFT
Un autre avantage du IFTE est que le programme à exécuter peut
venir d'un autre programme, il y a modularité.
Le Speed Case.
Ce n'est pas une structure de la HP, c'est
une bidouille de programmeurs destinée à accélérer le case. Elle se
sert des instructions POS et GET pour simplifier le case.
{ « Programme par défaut »
« Programme si cas 1 »
« Programme si cas 2 »
........................
« Programme si cas N »
}
{ Cas 1
Cas 2
.....
Cas N
}
ROT
POS
1
GET EVAL
Ce bout de programme prend au niveau 1
l'objet à tester et évalue le programme voulu.
Il pause sur la
pile la liste des programmes et la liste des cas, il met au niveau 1
l'objet à tester (ROT), il recherche sa position dans la liste des cas
(POS), il ajoute 1 (s'il n'est pas dans la liste, POS renvoie 0; comme
dans la liste des programmes le programme 0 est le programme par
défaut, le programme 2 dans le cas 1 ETC, tout colle pile-poil) il
récupère le programme à exécuter (GET) et il l'évalue
(EVAL).
Les variables locales.
Introduction.
Sur la HP48, il existe deux sortes de variables: Les variables locales et les variables globales. Vous connaissez tous les variables locales, c'est celles ou vous stockez vos gruges (les variable du menu VAR koi!). Les variables locales ne sont pas stokes en VAR, elles sont directement en RAM. Les variables locales sont uniquement accessibles dans un programme. Elles servent au programmeur pour stoker des données tem
rairement. Mais me direz vous , pourquoi ne pas utiliser les variable
globales.Il vaut mieux utiliser des variables locales dans un
programme et ceci pour 3 raisons:
Elles sont prévues pour
ca.
Elles sont plus rapide en accès.
Elles se 'gèrent' toutes
seules.
La consommation mémoire est moindre.
Elles permettent
l'empilement et donc la récursivité.
Utilisation des variables locales.
Si l'on veut utiliser des variables locales dans un
programme, il faut d'abord les 'déclarer'. C'est a dire qu'il faut
dire a la HP les identificateurs qui sont des variables locales de
manière a les différencier des variables globales.
-> A
B C @ Je déclare et j'initialise
@ A, B
et C
«
Programme utilisant A, B et
C
»
Ici, on vois un bout de programme déclarant de
3 variables locales A, B et C qui pourrons être utilisées dans le
programme .
La déclaration sert aussi d'initialisation, c'est a dire que si je fait 5 3 1 -> A B C « ... », cela déc
rera A, B et C et les initialisera respectivement a 5, 3 et 1
.
Ces variables aurons une existence entre l'ouverture du
programme et sa fermeture, mais des le programme ferme, elles seront
'purgées'.
Dans le programme, je peut me servir de A, B et C
comme variables, je peut me servir de toutes les fonction de
traitement des variables sur elles (INCR, DECR, STO, STO+, STO-, ...)
mais pas de PURGE car elles s'effacent toutes seules a la fin du
programme. Il faut aussi savoir que contrairement a une globale,
l'appel d'une locale correspond a un RCL et non a un EVAL. Si je
stocke un programme dans une globale et que je l'appelle, le programme
sera évalué, alors que si je place un programme dans une locale et que
je l'appel, le programme sera pose sur la pile .
PS: On peut
aussi déclarer une expression algébrique utilisant des locales:
->
A B C 'A+B+SIN(C-A^B*COS(C-A))'
Notions d'empilement.
Les variables locales peuvent s'empiler, c'est a dire que l'on peut dans un programme
ilisant une variable locale déclarer un autre programme utilisant des
locales.. Ces locales peuvent de plus avoir le même nom, on n'a alors
accès qu' a la dernière .
« 45 -> A
«
65 15 -> A B
« 12 -> B
« A B @ Renvoie 65 et 12
»
A B @ Renvoie 65 et 15
»
A @
Renvoie 45 (Ici, B n'existe pas)
»
»
Vous me direz que cela ne sert a rien qu'il suffit de ne pas faire
des locales avec le même nom.
Mais il se trouve que si une
fonction ce rappelle luis même, ce qui correspond a une technique de
programmation appelée récursivité, si cette fuction déclarer des
locales, a chaque appel récursif, elle crée de nouvelles variable
portant le même nom.
Exemple d'utilisation.
Voici un petit exemple de programme récursif. c'est a dire qu'il comporte une petite procédure qui se rappelle elle même. Cette procédure est stockée dans la variable locale R ce qui permet de ne pas avoir deux programmes: in programme d'initialisation et un pro
amme contenant la procédure. On peut y remarquer la petite 'bidouille'
permettant de le faire. On n'initialise pas la variable R avec la
procédure car cela obligerait a se servir de R alors que l'on a pas
encore déclarer que c'était une locale. Par contre, une fois le
programme ouvert, on peut taper une programme contenant R qui sera
alors considérée comme une variable locale.
« 9 { #
0h # 0h }
PVIEW (20,20) (2,0) 0
-> C D R
«
(0,1) SWAP
« IF DUP
THEN 1 - (0,1)
OVER R EVAL C DUP D +
DUP 'C' STO LINE SWAP
'D' STO* (0,-1)
SWAP
R EVAL
ELSE
DROP2
END
»
DUP
'R' STO
EVAL
»
»
Autre exemple, celui si est fort cours (mais des plus utiles). Il prend sur la pille un nom (local, global ou un nom d'objet de port), et envoi l'objet qui y est contenu. l'intérêt est surtout pour les librairie car on peut alors les envoyer sans être oblige de les recopier en VAR, c'est a dire que l'on a pas besoins de deux foi
la RAM pour les envoyer.
« -> A
«
'A' SEND
»
»
Gros problèmes des locales, et comment les résoudre.
Le problème.
Imaginons que je suis en train de faire un gros programme avec
pleins de sous programmes dans des variables a part, je ne peut pas me
servir dans un sous programme des variables locales définies par le
programme appelant.
si j'ai le programme TOTO
suivant:
« 1 -> A
« TITI
»
»
Je ne peut pas me servir de A dans TITI car lorsque l'on stocke le
programme dans TITI, la HP ne sait pas que c'est un sous programme de
TOTO, et donc elle ne sait pas que le A sera une variable locale et
non une variable globale.
Le problème est donc de trouver un
système pour pouvoir quand même utiliser A dans TITI.Il y a deux
solutions au problème: celle que nous avons trouve, et l'anti bug
bonux mis au point par HP dans la HP48Gx.
Le système HPuser .
La réflexion est simple: Dans le programme TO
, A existe en tant que variable locale, donc si je met un HALT dans
TOTO, lorsque la HP me rendra la main, elle sera encore dans TOTO et
donc A existera, donc si j'édite TITI a ce moment, il prendra aussi le
A pour une variable locale et non une variable Globale. le tour est
alors joue.
Le système HP (Sur G uniquement).
Chez HP, ils on adopter une autre solution, ils on décidés de différencier les
variables locales des variables globales. Ainsi sur HP48Gx, une
variable commencent par <- est une variable locale. Donc si je
fait
« -> <-A
« TITI
»
»
<-A est utilisable dans TITI sans avoir a utiliser le bidouille HPuser.
© Copyright 1999 FTLS (Tyndiuk Frédéric). All rights reserved.
Last Update 08/03/2000 - Send all comments to webmaster@ftls.org