Question

I want to do something like that in Common Lisp:

(defparameter *fun* 
  (lambda () x))

(let ((x 0))
  (funcall *fun*)) ;should return 0

I want to access a local binding in a function, that is not defined, when I define the function.

If I use x as parameter, it would work, but I can't change the value of the variable:

(defparameter *fun* 
  (lambda (x) (setf x (+ x 1))))

(let ((x 0))
  (funcall *fun* x)) ;should return 1, would return 0

How can I do what I want?

Was it helpful?

Solution

You can declare the variable special (dynamic) at both the binding site and the reference site:

(defparameter *fun* 
  (lambda () (declare (special x)) x))

(let ((x 0))
  (declare (special x))
  (funcall *fun*))

Or globally:

(defvar *x*)  ;; makes *x* special

(defparameter *fun* 
  (lambda () *x*))

(let ((*x* 0))
  (funcall *fun*))

Late edit:

A macro might serve you better in this scenario. The only lexical bindings a function can access are the ones that were present when it was created. For example, the behavior you described is given by the standard in the macro incf. Define-modify-macro is a helper for defining macros similar to incf. http://www.lispworks.com/documentation/HyperSpec/Body/m_defi_2.htm

OTHER TIPS

You can define the function in the nested scope:

[2]> (defparameter *fun* (let ((x 0)) (lambda () (setf x (+ x 1)))))
*FUN*
[3]> (funcall *fun*)
1
[4]> (funcall *fun*)
2

If your function is defined outside the scope of a lexical variable, it can't access that variable, by definition of what is lexical scope. To be able to do that, it must be inside that scope.

The other way around this issue is to make the variable special, giving it dynamic extent:

[5]> (defparameter *x* 1)
*X*
[11]> (defun fun () (setf *x* (+ *x* 1)))
FUN
[12]> *x*
1
[13]> (fun)
2
[16]> *x*
2
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top