next up previous contents index
Next: unwind-protect Up: Sauts non locaux Previous: return et return-from   Contents   Index

catch et throw

Un autre mécanisme de saut est implémenté par le couple d'opérateurs spéciaux catch et throw.

L'opérateur catch prend une expression dont la valeur est appelée étiquette (en Anglais : tag) et une suite d'expressions qui sont évaluées dans l'ordre (progn implicite).

L'opérateur throw prend une expression dont la valeur doit être une étiquette ainsi qu'une deuxième expression elle aussi évaluée.

Si, pendant l'évaluation de l'une des expressions de l'opérateur catch, une expression throw ayant la même étiquette (au sens de eq) est évaluée, un saut est effectué à la fin de l'expression catch, et la valeur de l'expression catch est l'ensemble des valeurs de la deuxième expression du throw. Exemple :

* (defun f ()
    (throw 'hello (floor 6 1.1)))

F
* (defun g ()
    (catch 'hello
      (print 'one)
      (f)
      (print 'two)))

G
* (g)

ONE
5
0.49999988
*

Il est courant d'utiliser un symbole comme étiquette, car on est sûr que deux symboles de même nom sont eq. Mais n'importe quel objet Common Lisp peut aussi être utilisé :

* (defparameter *bonjour* (make-array '(10)))

*BONJOUR*
* *bonjour*

#(0 0 0 0 0 0 0 0 0 0)
* (defun f ()
    (throw *bonjour* (floor 6 1.1)))

F
* (defun g ()
    (catch *bonjour*
      (print 'one)
      (f)
      (print 'two)))

G
* (g)

ONE
5
0.49999988
*

Alors que return-from est un mécanisme lexical, throw est dynamique. L'exemple ci-dessus fonctionne bien que l'expression throw ne soit pas imbriquée dans l'expression catch.


next up previous contents index
Next: unwind-protect Up: Sauts non locaux Previous: return et return-from   Contents   Index
Robert STRANDH
2001-09-28