Blocs

Le bloc le plus simple est progn. C'est un opérateur spécial acceptant un nombre arbitraire non nul d'arguments. Chaque argument est une expression et ces expressions sont évaluées séquentiellement. La valeur de toutes les expressions sauf la dernière est perdue. La valeur de l'expression progn toute entière sera la valeur de la dernière expression de la séquence (d'où le `n' de progn : la valeur de la n-ième expression est renvoyée). Puisque leur valeurs sont perdues, les premières expressions devraient toujours avoir des effets de bord. Exemple :

* (+ 5 (progn
         (setf *read-base* 10)
         (print *print-base*)
         7))

10
12
*

Plusieurs macros Common Lisp admettent une suite d'expressions et renvoient la valeur de la dernière sans nécessité de progn explicite. On parle de progn implicite (en Anglais : implicit progn). C'est le cas de defun, let, cond, etc.

Il est souvent nécessaire de mémoriser temporairement une valeur, puis d'évaluer des expressions et finalement de renvoyer cette valeur temporaire. Par exemple dans une fonction qui renvoie le sommet d'une pile, puis dépile la pile, on trouve souvent des constructions similaires à celle-ci :

(let ((temp (car stack)))
  (setf stack (cdr stack))
  temp)

Cette construction est si fréquente que Common Lisp fournit la macro prog1 qui permet d'écrire cela plus simplement :

(prog1 (car stack) (setf stack (cdr stack)))
Cette dernière construction est aussi tellement fréquente que Common Lisp fournit la macro pop qui permet de simplifier au maximum :

(pop stack)

Comme progn, prog1 prend une séquence d'expressions, cependant prog1 nécessite au moins une expression. Les expressions sont évaluées séquentiellement de la même manière qu'avec progn, mais c'est la valeur de la première expression qui sera la valeur de l'expression prog1 entière.

Il existe également une construction prog2, similaire à prog1, mis à part que c'est la valeur de la deuxième expression qui est renvoyée.

Un autre type de bloc très utile est block, qui correspond à un progn nommé. Le nom permet l'exécution d'une expression return-from permettant de sortir immédiatement du bloc avec une valeur donnée. Exemple :

* (block totals
    (loop for i from 0 to 100
          do (when (> i 20)
               (return-from totals (+ i 5)))))

26
*

D'autres types de blocs plus esotériques comme progv, prog et tagbody existent également.

Irene DURAND
2011-10-14