7.4 Последовательное выполнение

Все конструкции в данном разделе выполняют все формы аргументов в прямой последовательности. Различие заключается только в возвращаемых ими результатах.

[Специальный оператор] progn {form}*

Конструкция progn принимает некоторое количество форм и последовательно вычисляет их слева направо. Значения всех кроме последней формы игнорируется. Результатом формы progn становиться то, что вернула последняя форма. Можно сказать, что все формы кроме последней выполняются для побочных эффектов, а последняя форма для значения.

progn является примитивной управляющей структурой для «составных выражений», как блоки begin-end в Algol’ных языках. Много Lisp’овых конструкций является «неявным progn»: так как часть их синтаксиса допускает запись нескольких форм, которые будут выполнены последовательно и возвращён будет результат последней формы.

Если последняя форма progn возвращает несколько значение, тогда все они будут возвращены из формы progn. Если форм в progn нет вообще, то результатом будет nil. Эти правила сохраняются также и для неявного progn.


[Макрос] prog1 first {form}*

prog1 похожа на progn за исключением того, что он возвращает результат первой формы. Все формы-аргументы выполняются последовательно. Значение первой формы сохраняется, затем выполняются все формы, и, наконец, возвращается сохранённое значение.

prog1 чаще всего используется, когда необходимо вычислить выражение с побочными эффектами и возвращаемое значение должно быть вычислено до побочных эффектов. Например:

(prog1 (car x) (rplaca x ’foo))

изменяет car от x на foo и возвращает старое значение.

prog1 всегда возвращает одно значение, даже если первая форма возвращает несколько значений. В следствие, (prog1 x) и (progn x) могут вести себя по-разному, x возвращает несколько значений. Смотрите multiple-value-prog1. И хотя prog1 может использоваться для явного указания возврата только одного значения, для этих целей лучше использовать функцию values.


[Макрос] prog2 first second {form}*

prog2 похожа на prog1, но она возвращает значение её второй формы. Все формы-аргументы выполняются последовательно. Значение второй формы сохраняется и возвращается после выполнения остальных форм. prog2 представлена по большей части по историческим причинам.

(prog2 a b c ... z)  (progn a (prog1 b c ... z))

Иногда необходимо получить один побочный эффект, затем полезный результат, затем другой побочный эффекта. В таком случае prog2 полезна. Например:

(prog2 (open-a-file) (process-the-file) (close-the-file))
;возвращаемое значение process-the-file