Dans vos programmes Scheme, vous avez utilisé
#f,
#t,
12,
1.2,
"Scheme est beau"...
ce sont des
constantes, les deux premières étant les constantes
booléennes, les deux suivantes des constantes numériques et la
dernière une constante chaîne de caractères.
constante
booléen
#t ou
#f
nombre
12
chaine
"DEUG MIAS"
Mais vous avez aussi utilisé
*,
ma-L,
map,
if... ce sont des
symboles. Noter bien que chaque
symbole, même s'il est constitué de plusieurs lettres est considéré
comme une entité, Scheme ne regardant pas comment il est
« fabriqué ».
Remarques:
-
parmi les symboles précédents, if est un mot clef,
- les autres symboles sont des identificateurs qui identifient des
fonctions ou des variables (et on n'a pas le droit d'utiliser un mot
clef comme identificateur);
- vous avez aussi utilisé
-
l'espace et le retour chariot qui sont des séparateurs
permettant de séparer les différents symboles,
- les parenthèses,
- le point-virgule.
- depuis le début de ce cours, nous avons beaucoup utilisé les
chaînes de caractères; c'est parce que nous n'avions pas la
citation à notre disposition! En fait, presque tous les exemples
que nous avons vus, presque tous les exercices que vous avez faits
-- voire tous --, en « bon » Scheme seraient écrits en utilisant des
symboles que l'on citerait.
Vous vous êtes peut-être demandé pourquoi, par exemple dans
l'exemple donné pour la fonction
append, nous écrivions les
listes données
(list 1 2 3) et
(list 4 5 6 7) et que
nous disions que la liste résultat était
(1 2 3 4 5 6 7).
Pourquoi ne peut-on écrire, comme liste donnée
(1 2 3)?
En Scheme, programmes et valeurs sont représentés par des listes ou
des symboles, la notation
(...) indiquant une application
fonctionnelle ou une forme spéciale. Ainsi, si dans le programme nous
écrivons
(1 2 3), l'interprète va vouloir appliquer la
fonction nommée 1, qui, bien sûr n'existe pas, aux deux arguments 2
et 3. En fait, ce que nous voudrions, c'est
citer la valeur
de la liste
(1 2 3) à l'intérieur du programme.
Pour pouvoir
citer des valeurs à l'intérieur d'un programme, on
utilise la forme spéciale
quote ou son abréviation, le caractère
apostrophe (
'):
citation
(quote donnée)
' donnée
donnée
constante
symbole
( donnée)
Attention,
quote et
' n'ont pas la même syntaxe:
(quote e) º 'e.
Notations: dans ce paragraphe,
º sera lu « notation
équivalente » et --> sera lu « est évalué, par définition du
quote, en ».
(quote ab) ou encore
'ab désigne le
symbole « ab »
(quote ab) º 'ab -->
ab
et
(cons(quote ab)(quote ())) ou encore
(cons
'ab '()) construit la liste
(ab)
(cons(quote ab)(quote ())) º (cons 'ab '()) -->
(ab)
La citation d'un nombre est le nombre lui-même:
(quote 2) º '2 --> 2
et il en est de même pour toutes les constantes (booléennes et chaînes
de caractères).
La citation d'une liste (suite d'expressions séparées par des espaces
et entourées par des parenthèses) est la liste des citations des
expressions. Par exemple:
(quote (a b c)) º '(a b c)
-->
(list 'a 'b 'c) -->
(a b c)
(quote (1 2 3)) º '(1 2 3)
-->
(list 1 2 3) -->
(1 2 3)
(quote ((1 I) (2 II) (3 III)))
º
'((1 I) (2 II) (3 III))
-->
(list '(1 I) '(2 II) '(3 III))
-->
(list (list 1 'I) (list 2 'II) (list 3 'III))
-->
((1 I) (2 II) (3 III))
Attention:
a priori, ne pas « quoter » les
symboles à l'intérieur d'une liste « quotée ».
Un exemple plus compliqué?
Écrivons une fonction,
calculette, qui effectue les
opérations élémentaires:
(calculette 6 '+ 3) ->
9
(calculette 6 '* 3) ->
18
(calculette 6 '- 3) ->
3
(calculette 6 '/ 3) ->
2
On peut écrire:
;;;
;;;
;;;
;;;
;;;
(define (calculette-0 arg1 op arg2)
(cond ((equal? op '+) (+ arg1 arg2))
((equal? op '*) (* arg1 arg2))
((equal? op '-) (- arg1 arg2))
((equal? op '/) (/ arg1 arg2))))
Remarque: on aurait aussi pu prendre
NUPLET[Nombre Operateur Nombre] -> Nombre
comme profil de la fonction. Excellent exercice!
Mais on peut donner une autre solution. En fait, ce qu'il nous
faudrait, c'est une fonction qui associe, à un opérateur (qui est un
symbole) l'opération (qui est une fonction) correspondante:
;;;
;;;
;;;
;;;
et la définition irait alors de soi:
;;;
;;;
;;;
;;;
;;;
(define (calculette arg1 op arg2)
((operation op) arg1 arg2))
Remarque: noter que
(operation op) rend une fonction et
((operation op) arg1 arg2) est une application de cette fonction avec comme arguments
arg1 et
arg2.
Pour la définition de
operation, on peut penser à une liste
d'associations, les clefs étant les symboles (opérateurs) et les
valeurs étant les opérations et l'extraction de l'opération
correspondant à un opérateur, est exactement le problème valeur-de que
nous avons vu lors de l'étude des listes d'associations:
;;;
;;;
;;;
;;;
(define (operation symbole)
(let ((liste-a (list (list '* *)
(list '+ +)
(list '- -)
(list '/ /))))
(cadr (assoc symbole liste-a))))
Noter l'écriture de la liste d'associations: on ne peut pas écrire
cette expression en n'utilisant que le quote (puisque le quote d'une
liste quote les éléments de la liste, or dans notre exemple, il y a
des éléments des listes qui ne sont pas quotés).