Sylwester's answerはこれを非常によく説明していますが、より明白な副作用のある例がこれをより明確にする場合は、次のことを考慮してください。
CL-USER> (defparameter *foo* (progn (print 'hello) 0))
HELLO
*FOO*
CL-USER> *foo*
0
CL-USER> *foo*
0
の定義*foo*では、(progn (print 'hello) 0)は 1 回評価されるため、helloが出力され、値は0であり、これが の値になります*foo*。*foo*後で評価するということは、*foo*の値 ( 0) , not reëvaluating the form that produced its original value. In contrast, consider calling a function whose body is(progn (print 'hello) 0)`を検索することを意味します。
CL-USER> (defun foo () (progn (print 'hello) 0))
FOO
CL-USER> (foo)
HELLO
0
CL-USER> (foo)
HELLO
0
CL-USER> (foo)
HELLO
0
fooが呼び出されるたび(progn (print 'hello) 0)に評価され、hello出力されて0返されます。この例を見た後、コードは少し明確になるはずです。
(defparameter *lfn*
(let ((count 0))
#'(lambda ()
(incf count))))
(let ...)は一度評価され、その評価が の値を生成するクロージャーです*lfn*。一方では、
(defun testclosure ()
(let ((count 0))
#'(lambda ()
(incf count))))
(let ...)が呼び出されるたびに評価され、そのたびtestclosureに新しいクロージャーが返されます。