A better way to understand what
progn is is by comparing it to the family:
2 part of the name stands for the statement from the list whose result you are interested in. In other words,
progn will return the result of the last statement it contains, whereas
prog1 will return the first, and similar for
Today this functionality seems a little awkward since we learn to either expect the program to return in the last statement, or to instruct it explicitly what to return. Thus
prog2 are very seldom used. However, if you think about it, it makes sense, and here is how:
Different programming languages use different strategies to describe their semantics. Lisp family used to be tightly tied to denotational semantics. Without going into much detail, this kind of semantics has particular difficulty with something we grew to know as "statements", which are not "expressions". Meanings of code are typically thought in terms of function combinations, while a "statement" which cannot be even described as a function (since it doesn't evaluate to anything) is thus difficult to deal with. However, since Lisp permits side-effects, sometimes a programmer would want to use an expression without using its value in a way that it doesn't affect the expression following it. And this is where
progX family comes in.
In C-like languages this feature is sometimes known as sequence point (i.e.
, for example).
progn is as essential to Lisp-like languages as
; is to C-like languages. It is a fundamental feature of the language one cannot easily replace. However, unlike in C-style languages, Lisp tends to build syntactical abstractions by completely hiding the syntax of the lower level. And this perhaps why you don't see
progn used all that often, yet it is one of the important building blocks, when it comes to building higher level language abstractions (s.a. macros).