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
に新しいクロージャーが返されます。