Valeurs multiples

Souvent on souhaiterait qu'une fonction renvoie plusieurs valeurs ou aucune valeur, au lieu d'une valeur unique. Common Lisp propose un mécanisme qui réalise exactement ce souhait.

Plusieurs fonctions primitives Common Lisp renvoient déjà deux valeurs. Nous l'avons déjà vu dans la section 6.2.9 pour les fonctions floor et ceiling :

* (floor 5 1.3)

3
1.1000001
*

Ici, la première valeur indique le quotient de la division et la deuxième valeur indique le reste.

Dans un contexte où une seule valeur est attendue, c'est la première qui est utilisée et la deuxième est perdue :

* (* (floor 5 1.3) 2)

6
*

La deuxième valeur peut être récupérée grâce à la macro multiple-value-bind. Cette macro prend comme paramètres une liste de variables destinées à contenir les valeurs, une expression renvoyant plusieurs valeurs et un corps d'expressions qui seront évaluées dans le contexte des variables :

* (multiple-value-bind (x y)
      (floor 5 1.3)
    (+ x y))

4.1000004
*

Le programmeur Common Lisp peut écrire ses propres fonctions ayant plusieurs valeurs, grâce à l'accesseur values :

* (defun sumdiff (x y)
    (values (+ x y) (- x y)))

SUMDIFF
* (sumdiff 45 33)

78
12
*

L'opérateur spécial progn permet à la dernière expression de renvoyer plusieurs valeurs, mais la macro prog1 ne renvoie que la première valeur de son premier argument. Afin de récupérer toutes les valeurs, on utilise la macro multiple-value-prog1 :

* (progn (cos 10) (values 1 2))

1
2
* (prog1 (values 1 2) (cos 10))

1
* (multiple-value-prog1 (values 1 2) (cos 10))

1
2
*

Une implémentation de Common Lisp peut limiter le nombre de valeurs multiples possibles. La variable multiple-values-limit indique cette limitation :

* multiple-values-limit

536870911
*

Même si, dans le cas CMUCL, cette valeur n'est pas très restrictive, le mécanisme de valeurs multiples n'est souvent utile que pour un nombre relativement faible de valeurs, au plus une dizaine.

Irene DURAND
2011-10-14