Search code examples
common-lisp

Necessity of “Progn” Becoming “Special Operator”


If progn is NOT a special operator, it could be defined as macro like this:

(defmacro progn (&rest body)
  `(let ()
     ,@body))

I guess that defmacro's definition may have used some progns, but it only needs to substitute (let () ...)s for those (progn ...)s.

Less special operators, more elegant. Am I wrong?


Solution

  • [This answer concerns Common Lisp, not Lisp in general.]

    progn must be special at least because it must be handled specially at top-level. In particular when compiling a file containing, say

    (defun foo ...)
    (progn
      (defun bar ...)
      (progn
        ...))
    

    Then the forms inside the progns are at top-level and are recognised as such by the compiler. In contrast in a file containing

    (defun foo ...)
    (let ()
      (defun bar ...))
    

    The forms inside the let are not at top-level, and are therefore not recognised as such by the compiler. This matters quite a lot in some cases, and it means that your definition of progn is not correct and that it is not in fact possible to define progn without resorting to progn in the definition.

    However, it clearly is the case that CL has more special operators than it strictly needs. For instance you can easily make let out of lambda in the obvious way, so let is not really needed. I don't think anyone ever argued that CL's set of special operators was strictly minimal, because CL was not designed to be a strictly minimal Lisp.