问题
I assumed that values passed into a lisp function are assigned to a quote matching the name of the parameter. However, I was surprised that this:
(defun test (x) (print (eval 'x)))
(test 5)
doesn't work (the variable x is unbound). So if parameters aren't stored as symbols in the function, what exactly IS x in this example? Is there a way to access parameters from a symbol matching the parameter name?
More context: What I would like to do is something like this:
defun slice (r1 c1 r2 c2 board)
(dolist (param '(r1 c1 r2 c2)) ;adjust for negative indices
(if (< (eval param) 0)
(set param (+ (length board) (eval param)))))
;Body of function
Basically, I want to iterate through the first four parameters and make an adjustment to any of their values if they are < 0. Of course, I could do a let and have an individual line for each parameter, but considering I'm doing the same thing for each of the four parameters this seemed cleaner. However, I get the error that the variable R1 is unbound.
回答1:
Is there a way to access parameters from a symbol matching the parameter name?
Not for lexical binding. Common Lisp gives no way to access a lexical variable from a similar named symbol. You would need to declare the variable special.
So if parameters aren't stored as symbols in the function, what exactly IS x in this example?
A processor register? A part of a stack frame?
With dynamic binding:
CL-USER 40 > (defun foo (a b)
(declare (special a b))
(dolist (v '(a b))
(if (zerop (symbol-value v))
(set v 10)))
(values a b))
FOO
CL-USER 41 > (foo 1 0)
1
10
回答2:
That's basically how lexical binding works: the variable name gets replaced within the lexical scope with a direct reference to where the variable's value is stored. Binding the variable name's symbol-value
is only done for dynamic variable which you can declare with special
.
One way to avoid repeating yourself would be a macro:
(defmacro with-adjusting ((&rest vars) adjust-value &body body)
`(let ,(loop for var in vars
collect `(,var (if (minusp ,var)
(+ ,var ,adjust-value)
,var)))
,@body))
(defun slice (r1 c1 r2 c2 board)
(with-adjusting (r1 c1 r2 c2) (length board)
;; function body
回答3:
As Rainer explained, you cannot access the lexical argument value by its name.
What you can do instead is use the &rest argument together with destructuring-bind if you want the variables too:
(defun slice (board &rest params)
(destructuring-bind (r1 c1 r2 c2)
(mapcar (lambda (param) ;adjust for negative indices
(if (minusp param)
(+ (length board) param)
param))
params)
... operate on r1 c1 r2 c2 ...))
来源:https://stackoverflow.com/questions/19407209/how-are-function-parameters-stored-in-lisp