| Maciej Katafiasz 2007-11-22, 4:30 am |
| Den Thu, 22 Nov 2007 00:05:54 -0800 skrev Larme:
> I'm not sure if I'm right but I think in lisp function parameters are
> passing-by-value hence if we have:
Nope. Actually, it's neither by-value nor by-reference, it's
by-binding (for lack of a better term).
> CL-USER> (defun add1 (x) (setf x (+ x 1))) ADD1
> CL-USER> (setq n 9)
> 9
> CL-USER> (add1 n)
> 10
> CL-USER> n
> 9
>
CL-USER> (setf *n* 9)
CL-USER> (defun add1 (x) (setf x (+ x 1))
(format t "*n*: ~A, x: ~A~%" *n* x))
ADD1
CL-USER> (add1 *n*)
*n*: 9, x: 10
NIL
CL-USER> (defun by-val? ()
(let ((foo 10))
(format t "foo: ~A~%" foo)
(let ((bar foo))
(format t "foo: ~A, bar: ~A~%" foo bar)
(setf bar 20)
(format t "foo: ~A, bar: ~A~%" foo bar))))
BY-VAL?
CL-USER> (by-val?)
foo: 10
foo: 10, bar: 10
foo: 10, bar: 20
If you understand why BY-VAL? does what it does, you're gold. What
happens is that each time you establish a new binding, its value gets
initialised with a copy of the supplied *binding*, that is, both the
new and old variables are bound to the same place. But after that, the
new one takes a life on its own, so when you change it, it won't get
reflected in the original one. It's equivalent to copying a pointer,
and then changing the pointer itself, not the object it points to. The
modification would be visible outside only if you modified the
referenced object, and you don't by just SETF'ing a binding. And if
you now consider the fact that a defun introduces new lexical bindings
for all of the formal parameters in its lambda list, the rest should
be obvious.
Cheers,
Maciej
PS. Use SETF rather than SETQ. And surround your special vars with *'s.
|