5

我假设传递给 lisp 函数的值被分配给与参数名称匹配的引号。然而,令我惊讶的是:

(defun test (x) (print (eval 'x)))
(test 5)

不起作用(变量 x 未绑定)。因此,如果参数不作为符号存储在函数中,那么这个例子中的 x 到底是什么?有没有办法从与参数名称匹配的符号访问参数?

更多上下文:我想做的是这样的:

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

基本上,我想遍历前四个参数并调整它们的任何值(如果它们 < 0)。当然,我可以做一个 let 并为每个参数设置一个单独的行,但考虑到我正在做四个参数中的每一个都相同,这看起来更干净。但是,我收到变量 R1 未绑定的错误。

4

3 回答 3

5

这基本上就是词法绑定的工作原理:变量名在词法范围内被替换为对变量值存储位置的直接引用。绑定变量名symbol-value仅适用于您可以声明的动态变量special

避免重复自己的一种方法是宏:

(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
于 2013-10-16T16:42:00.007 回答
4

有没有办法从与参数名称匹配的符号访问参数?

不适用于词法绑定。Common Lisp 无法从类似的命名符号中访问词法变量。您需要声明变量special

因此,如果参数不作为符号存储在函数中,那么这个例子中的 x 到底是什么?

处理器寄存器?堆栈帧的一部分?

使用动态绑定:

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
于 2013-10-16T15:27:01.660 回答
2

正如 Rainer 所解释的,您不能通过名称访问词法参数值。

如果您也想要变量,您可以做的是与&rest参数一起使用:destructuring-bind

(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 ...))
于 2013-10-16T16:01:55.097 回答