return et return-from

Nous avons déjà mentionné l'opérateur spécial return-from dans le chapitre 10. Cet opérateur permet d'abandonner l'évaluation des expressions dans un bloc. Cet opérateur est capable de dépiler des appels en cours :

* (block here
    (labels ((recfun (n)
               (if (zerop n)
                   (return-from here 22)
                   (progn (recfun (1- n))
                          (print "hello")))))
      (recfun 10)))

22
*

Ici, les dix invocations de la fonction recfun sont abandonnées lorsque l'expression return-from est évaluée. L'expression print n'est donc jamais évaluée.

Un bloc implicite est établi par l'invocation d'une fonction. Ce bloc porte le nom de la fonction. Il est donc possible d'utiliser return-from pour sortir d'une fonction :

* (defun fun (n)
    (labels ((recfun (n)
               (if (zerop n)
                   (return-from fun 22)
                   (progn (recfun (1- n))
                          (print "hello")))))
      (recfun n)))

FUN
* (fun 10)

22
*

La macro return permet d'économiser quelques caractères lorsque le nom du bloc est nil.

Le mécanisme return-from est lexical, à savoir que l'étiquette du bloc n'est accessible qu'aux expressions qui sont à l'intérieur du bloc. L'exemple suivant n'est donc pas possible :

* (defun f ()
    (return-from g 11))

F
* (defun g ()
    (f))

G
* (g)
message d'erreur

Irene DURAND
2011-10-14