Caractéristiques des applications en Scheme:
-
écriture préfixe,
- complètement parenthésée,
- les parenthèses entourent toute l'expression (i.e. la
fonction et les arguments),
- le séparateur est l'espace.
Exemples:
(+ 3 a)
On peut imbriquer les applications:
(+ (/ a c) (* 5 (sin (* b d))))
Remarque: les fonctions peuvent alors avoir un nombre
quelconque d'arguments. Par exemple:
(+ (* 3 x x) (* 5 x) 8)
On peut écrire les expressions sur plusieurs lignes, ce qui
améliore la lisibilité:
(+ (* 3 x x)
(* 5 x)
8)
Attention, ne pas confondre l'entier relatif -3 avec
l'expression
(- 0 3) ou l'expression
(- 3), qui ont la
même valeur, et avec l'expression
(- 3 0), qui vaut 3 et
(-3) (sans espace entre le tiret et le 3) qui donne une erreur,
-3 n'étant pas une fonction.
(- 0 3) -> -3
(- 3) -> -3
(- 3 0) -> 3
(-3) -> ERREUR
Dans une application, le premier élément est la
fonction (et,
comme nous le verrons plus tard, c'est elle-même une expression) que
l'on applique à des
arguments (qui sont eux-mêmes des
expressions). Par exemple, dans l'expression
(+ (* 3 7 7) (* 5 7) 8)
-
la fonction est +;
- les arguments sont (* 3 7 7), (* 5 7) et 8.
On définit comment doit être écrite une application en utilisant une
règle de grammaire:
application(fonctionargument)
Dans une telle règle de grammaire:
-
application, qui est avant la flèche et est écrit entre
chevrons (< et >), est l'unité syntaxique
que l'on est en train de définir;
- fonction et argument, qui sont écrits entre
chevrons (< et >), sont des unités syntaxiques
définies par une (autre ou celle que l'on est en train d'écrire)
règle de grammaire;
- ( et ) qui ne sont pas écrits entre chevrons
sont des terminaux et seront écrits tels quels dans les
sources Scheme.
Cette règle de grammaire dit qu'une application est constituée par une
parenthèse ouvrante suivie d'une fonction puis d'un nombre quelconque,
éventuellement 0, (c'est le sens de l'étoile) d'arguments et enfin
d'une parenthèse fermante.
En fait, les arguments sont des expressions quelconques (c'est ce qui
permet, entre autres, de pouvoir imbriquer les applications) et il en
est de même pour les fonctions:
argumentexpression
fonctionexpression
Dans le paragraphe précédent, nous avons défini comment doit être
écrite une application pour qu'elle puisse être « comprise » par
l'interprète Scheme. On dit que l'on a décrit la syntaxe du langage.
Il faut également savoir ce que représente une telle application,
autrement dit quelle est sa valeur. On dit que l'on définit la
sémantique du langage. En effet, la valeur de l'application calculée
par l'interprète doit correspondre au
sens que l'humain, qui
lit ou écrit le source du programme, donne à cette application.
Dans ce cours, nous donnerons trois formes de sémantiques:
-
tout d'abord une sémantique naïve où l'on décrit, « avec les
mains », la valeur que doit afficher un interprète Scheme,
- cette vision ne permettant pas de comprendre ce qui se passe
lorsque l'expression est complexe, nous donnerons ensuite une
sémantique plus formelle qui nous permettra de définir précisément
la valeur des expressions que nous écrirons en DEUG,
- enfin, l'interprète que nous écrirons dans la troisième partie
de ce cours est une autre forme de sémantique (on indique bien ainsi
ce que doit valoir une expression), bien sûr de nature très
différente.
Remarque: la sémantique formelle que nous donnerons par la
suite est suffisante pour décrire le sens des expressions Scheme que
nous écrirons en DEUG. Elle n'est pas assez puissante pour décrire le
sens de n'importe quelle expression Scheme.
Pour évaluer une application, on évalue chacun de ses arguments (ce qui
nous donne des valeurs) et on applique la fonction à ces valeurs. Par
exemple, pour évaluer l'application
(+ (* 3 7 7) (* 5 7) 8)
1 - on évalue les arguments:
(* 3 7 7) ->
147
(* 5 7) ->
35
8 ->
8
2 - on applique la fonction
+ aux arguments
147, 35 et 8:
(+ (* 3 7 7) (* 5 7) 8) ->
190
On peut visualiser ce processus de calcul en utilisant DrScheme et en
faisant évaluer l'expression en mode « pas à pas ».