alternative
Les expressions peuvent être définies par cas au moyen d'alternatives.
Par exemple:
;;;
;;;
(define (valeur-absolue x)
(if (>= x 0)
x
(- x)))
Notons que nous pourrions aussi utiliser le prédicat
negative? que nous avons définie ci-dessus:
;;;
;;;
(define (valeur-absolue-bis x)
(if (negative? x)
(- x)
x))
La syntaxe d'une alternative suit la grammaire suivante:
<alternative> |
-> |
(if <condition> <conséquence> )
|
|
|
(if <condition> <conséquence>
<alternant> ) |
|
|
|
<condition> |
-> |
<expression> |
|
|
|
<conséquence> |
-> |
<expression> |
|
|
|
<alternant> |
-> |
<expression> |
|
|
|
Remarques:
-
Une condition est une expression ayant pour valeur, soit vrai
(noté #t), soit faux (noté #f).
- Une conséquence et un alternant sont des expressions
quelconques.
- La règle de grammaire qui définit l'alternative est écrite sur
deux lignes et on peut donc prendre l'une ou l'autre des
possibilités. Dans un premier temps, nous n'utiliserons que la
deuxième.
Une alternative s'évalue ainsi: la condition est d'abord évaluée. Si
sa valeur est vraie, alors seulement la conséquence est évaluée (et la
valeur de l'alternative est égale à la valeur de cette évaluation)
sinon seulement l'alternant est évalué.
Ainsi, contrairement aux applications, pour une alternative, on ne
commence pas par évaluer tous ses composants: on dit qu'une
alternative est une
forme spéciale.
Les conditions peuvent être construites avec les opérations logiques
suivantes:
Tout d'abord la négation: il existe une fonction prédéfinie
not:
;;;
;;;
(define (valeur-absolue-ter x)
(if (not (negative? x))
x
(- x)))
Remarque: la fonction
not, qui rend un booléen, n'est
pas un prédicat, mais une opération car elle a comme donnée un booléen
(ainsi, elle a le même status que, par exemple, l'opération moins
unaire sur les entiers -- comme dans l'application
(- 3)).
On peut écrire aussi des conjonctions et des disjonctions en suivant
les règles de grammaire suivantes:
<conjonction> |
-> |
(and <expression>*) |
|
|
|
<disjonction> |
-> |
(or <expression>*) |
|
|
|
La conjonction et la disjonction ne sont pas des fonctions -- comme la
fonction
not -- mais des formes spéciales -- comme
l'alternative:
Pour évaluer
(and e1 e2 e3),
-
on évalue l'expression e1: si elle est fausse, toute
l'expression est fausse et on n'évalue pas e2 et e3;
- si e1 est vraie, on évalue l'expression e2: si
elle est fausse, toute l'expression est fausse et on n'évalue pas
e3;
- si e1 et e2 sont vraies, on évalue l'expression
e3: si elle est fausse, toute l'expression est fausse et si
elle est vraie, toute l'expression est vraie.
De même, pour évaluer
(or e1 e2),
-
on évalue l'expression e1: si elle est vraie, toute
l'expression est vraie et on n'évalue pas e2;
- si e1 est fausse, on évalue l'expression e2: si
elle est vraie, toute l'expression est vraie et si elle est fausse,
toute l'expression est fausse.
conditionnelle
L'alternative permet d'écrire des expressions dont la valeur est
spécifiée selon deux cas. S'il y a plus de deux cas, on écrit une
alternative dont la conséquence ou l'alternant est une alternative.
Considérons, par exemple, la fonction
signe spécifiée par:
;;;
;;;
On peut écrire une définition en utilisant des alternatives:
(define (signe x)
(if (< x 0)
-1
(if (= x 0)
0
1)))
Mais, au lieu d'utiliser une cascade d'alternatives, il est
préférable, pour la lisibilité, d'utiliser une conditionnelle:
(define (signe x)
(cond ((< x 0) -1)
((= x 0) 0)
(else 1)))
La syntaxe d'une conditionnelle suit la grammaire suivante:
<conditionnelle> |
-> |
(cond <clauses> )
|
|
|
|
<clauses> |
-> |
<clause> <clause>* |
|
|
<clause>*(else <expression> )
|
|
|
|
<clause> |
-> |
( <condition> <expression> )
|
|
|
|
Remarques:
-
La règle de grammaire qui définit <clause> est écrite
sur deux lignes et on peut donc prendre l'une ou l'autre des
possibilités. Nous n'utiliserons que la deuxième (et la dernière
clause est donc un else).
- Noter bien les parenthèses: il y a un couple de parenthèses pour
le cond, ce mot clef étant suivi de <clauses> qui
est une suite de <clause>s, chacune
des <clause>s étant constituée par un couple, entouré de
parenthèses, <condition>, <expression>. Ainsi, une
conditionnelle commence par (cond (<condition> et
comme la condition est, la plupart du temps, une expression non
réduite à une constante, elle commence elle-même par une parenthèse
et il y a donc deux parenthèses ouvrantes après cond.
Une conditionnelle s'évalue ainsi:
-
la condition de la première clause est d'abord évaluée; si sa
valeur est vraie, alors seulement l'expression de cette clause est
évaluée (et la valeur de la conditionnelle est égale à la valeur de
cette évaluation);
- sinon, la condition de la deuxième clause est évaluée; si sa
valeur est vraie, l'expression de cette clause est évaluée (et la
valeur de la conditionnelle est égale à la valeur de cette évaluation);
- ...
- si les évaluations de toutes les conditions rendent faux, la
valeur de la conditionnelle est égale à l'évaluation de l'expression
qui suit le else.
Les conditionnelles ne sont pas essentielles, car elles peuvent être
réécrites sous la forme d'alternatives:
(cond (else e)) devient e
(cond (c1 e1) (else e2))) devient (if c1 e1 e2)
(cond (c1 e1) (c2 e2) ... )) devient (if c1 e1 (if c2 e2 (if ....)))
Souvent, en mathématique ou dans le langage courant, les définitions
par cas sont données en spécifiant chacun des cas, indépendemment les
uns des autres. Par exemple, pour définir la valeur absolue d'un
nombre
x, on écrit souvent:
-
si x 0, alors la valeur absolue de x est égale à x,
- si x < 0, alors la valeur absolue de x est égale à -x.
Lorsque l'on traduit une telle définition dans un langage de
programmation, en particulier en Scheme, on doit -- pour l'efficacité
et la lisibilité -- supprimer les tests inutiles. Ainsi, dans la
définition Scheme que nous avons donnée, nous testons si
x est
supérieur ou égal à 0 et nous ne testons pas explicitement que
x
est inférieur à 0 (puisque, lorsque
x n'est pas supérieur ou égal
à 0, il est inférieur à 0).