我想在Common Lisp中做类似的事情:
(defparameter *fun*
(lambda () x))
(let ((x 0))
(funcall *fun*)) ;should return 0
我想在定义函数时访问未定义的函数中的本地绑定。
如果我使用x作为参数,它会起作用,但我不能改变变量的值:
(defparameter *fun*
(lambda (x) (setf x (+ x 1))))
(let ((x 0))
(funcall *fun* x)) ;should return 1, would return 0
我怎样才能做我想做的事?
答案 0 :(得分:6)
您可以在绑定站点和参考站点声明变量special(dynamic):
(defparameter *fun*
(lambda () (declare (special x)) x))
(let ((x 0))
(declare (special x))
(funcall *fun*))
或全球:
(defvar *x*) ;; makes *x* special
(defparameter *fun*
(lambda () *x*))
(let ((*x* 0))
(funcall *fun*))
延迟编辑:
在这种情况下,宏可能会更好地为您服务。函数可以访问的唯一词法绑定是在创建时存在的那些。例如,您描述的行为由宏incf中的标准给出。 Define-modify-macro是一个帮助器,用于定义类似于incf的宏。 http://www.lispworks.com/documentation/HyperSpec/Body/m_defi_2.htm
答案 1 :(得分:2)
您可以在嵌套范围中定义函数:
[2]> (defparameter *fun* (let ((x 0)) (lambda () (setf x (+ x 1)))))
*FUN*
[3]> (funcall *fun*)
1
[4]> (funcall *fun*)
2
如果您的函数是在词法变量的范围之外定义的,则根据词法范围的定义,它无法访问该变量。为了能够做到这一点,它必须在范围内。
解决这个问题的另一个方法是使变量特殊,给它动态范围:
[5]> (defparameter *x* 1)
*X*
[11]> (defun fun () (setf *x* (+ *x* 1)))
FUN
[12]> *x*
1
[13]> (fun)
2
[16]> *x*
2