(setq x nil)
(defun foo (var)
(if t
(setq var 1)
(setq var -1))
)
上面x是在foo函数外部定义的一个变量, 希望foo函数中,可以对其进行修改
执行(funcall 'foo x)
x好像没变呀
(setq x nil)
(defun foo (var)
(if t
(setq var 1)
(setq var -1))
)
上面x是在foo函数外部定义的一个变量, 希望foo函数中,可以对其进行修改
执行(funcall 'foo x)
x好像没变呀
(setq x nil)
(defun foo (var)
(if t (set var 1) (set var -1)))
x ; nil
(foo 'x)
x ; 1
setq
是宏,你的 foo
去掉 var
参数也能跑
注意到我用 set
替换掉了 setq
在这个场景下
(setq var 1)
宏展开后变为
(set 'var 1)
不会去读 var 里面是什么
如果开启了lexical-binding,实际上是无法把变量传给函数的。
;; -*- lexical-binding: t; -*-
(defun foo (var)
(if t
(set var 1)
(set var -1)))
(let ((x 0))
(foo 'x)
x) ; 结果还是 0
可行的方法是传一个cons,再函数里面修改cons cell的值。
(defun foo2 (cell)
(if t
(setcar cell 1)
(setcar cell -1)))
(let ((x (list 0)))
(foo2 x)
(car x)) ;; 1
如果想要修改变量里面的内容,那最好是传递列表或向量,它们是引用值而不是立即值,修改这些数据内部的内容是可行的:
(defun my-set (x val) (setcar x val))
(let ((x (list 1)))
(my-set x 2)
x)
=> 2
另外, gv.el 提供了一个通用的引用和解引用操作,在词法作用域下可以这样做:
(defun my-set2 (x val)
(setf (gv-deref x) val))
(let ((x 1))
(my-set2 (gv-ref x) 30)
x)
=> 30