Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

a question about variable bind in common lisp

It is a question about variable bind in function define:

If I define funcion "total" like this,x in "total" is bind to the local x in let.

CL-USER> (let ((x 0))
           (defun total (y)
             (incf x y)))
TOTAL
CL-USER> (defvar x 10000)
X
CL-USER> (total 1)
1

but,if I define "total" like this,x is bind to global x in defvar:

CL-USER> (defvar x 10000) 
X
CL-USER> (let ((x 0))
           (defun total (y)
             (incf x y)))
TOTAL
CL-USER> (total 1)
10001

Why this? I need an explanation to understand it. the environment is windows+emacs+slime+sbcl.Thanks.

like image 620
luosha865 Avatar asked Apr 22 '11 06:04

luosha865


1 Answers

DEFVAR establishes a symbol (here, X) as being a dynamic variable ("special"). Once that's been done, its dynamicity will be preserved by LET and lambda lists (this is one reason why you always name special variables with *earmuffs*). So in the second example, the X in TOTAL will be looked up in the dynamic environment of where TOTAL is called. When you call it at the top level, it sees the top-level binding of X where it has the value of 10000. You can also call TOTAL inside another LET that re-binds X and it will use that value for the duration:

* (let ((x 1000))
    (total 5)))
1005
* (total 1)
10002

In the first example, X hasn't been marked special, so LET binds it lexically, as normal. The subsequent DEFVAR doesn't retroactively affect TOTAL because the DEFUN has grabbed the lexical environment that LET created, and will use that for a reference to X (basically, hiding it from the DEFVAR.)

like image 82
Nietzche-jou Avatar answered Sep 27 '22 18:09

Nietzche-jou