Вопрос о связывании переменных в общем lisp
Речь идет о привязке переменной в функции define:
Если я определю функцию "total" следующим образом,x в "total" будет привязан к локальному x в let.
CL-USER> (let ((x 0))
(defun total (y)
(incf x y)))
TOTAL
CL-USER> (defvar x 10000)
X
CL-USER> (total 1)
1
но, если я определю "total" следующим образом,x будет привязан к глобальному x в defvar:
CL-USER> (defvar x 10000)
X
CL-USER> (let ((x 0))
(defun total (y)
(incf x y)))
TOTAL
CL-USER> (total 1)
10001
Почему это? Мне нужно объяснение, чтобы понять это. среда Windows+ Emacs+ Slime+ Sbcl. Спасибо.
1 ответ
DEFVAR устанавливает символ (здесь, X) как динамическую переменную ("специальная"). Как только это будет сделано, его динамичность будет сохранена с помощью LET и лямбда-списков (это одна из причин, почему вы всегда называете специальные переменные *earmuffs*). Таким образом, во втором примере X в TOTAL будет просматриваться в динамической среде, в которой вызывается TOTAL. Когда вы вызываете его на верхнем уровне, он видит привязку верхнего уровня X, где он имеет значение 10000. Вы также можете вызвать TOTAL внутри другого LET, который повторно связывает X, и он будет использовать это значение в течение продолжительности:
* (пусть ((х 1000)) (всего 5))) 1005 * (всего 1) 10002
В первом примере X не был отмечен как специальный, поэтому LET связывает его лексически, как обычно. Последующий DEFVAR не имеет обратной силы на TOTAL, потому что DEFUN захватил лексическую среду, созданную LET, и будет использовать ее для ссылки на X (в основном, скрывая ее от DEFVAR.)