How are function parameters stored in lisp?

好久不见. 提交于 2019-12-07 06:45:15

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!