0

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?

2 Answers 2

6

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

Sign up to request clarification or add additional context in comments.

2 Comments

I have to save my functions in lists, so it is not possible, to use macros, I think. I think declare and special is the best, but it seems not very beautiful. Maybe I simply use global parameters.
you only have to use declare special once outside the lambda-expression, so this is good
2

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

1 Comment

You might modify the example a little bit, though. The defparameter already has the effect of globally declaring *x* special, so it's redundant within fun. m-n's answer makes this a bit clearer by using (declare (special x)) within the let, and within the lambda.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.