【问题标题】:How are function parameters stored in lisp?lisp中函数参数是如何存储的?
【发布时间】:2013-10-24 18:59:34
【问题描述】:

我假设传递给 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

基本上,我想遍历前四个参数,如果它们

【问题讨论】:

  • 它是特定于实现的。 SBCL在Foreign Function Interface等章节中给出一些信息。

标签: function parameters lisp common-lisp


【解决方案1】:

这基本上就是词法绑定的工作原理:变量名在词法范围内被替换为对变量值存储位置的直接引用。绑定变量名的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

【讨论】:

  • 这是一个很好的答案。宏在这里非常有用。小缺点:编译后的代码变大了。
【解决方案2】:

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

不适用于词法绑定。 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

【讨论】:

  • 谢谢,这让我可以使用相同的代码,只增加一行来将参数声明为特殊
  • @murphyslaw 请确保您了解声明变量特殊的其他可能后果。该变量将与动态范围绑定,这意味着,例如,(let ((x 3)) (declare (special x)) (funcall (let ((x 4)) (declare (special x)) (lambda () x)))) 将返回3,而不是4,即使在创建lambda 函数时x 绑定到4。跨度>
  • @JoshuaTaylor - 感谢您的提醒,我显然需要对此进行更多阅读。可以肯定的是,将参数声明为特殊参数不会对功能块之外的符号产生任何影响,对吗?
  • 我想这取决于你所说的外部究竟是什么意思,但看看these examples
【解决方案3】:

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

如果您也需要变量,您可以将&amp;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 ...))

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-04-02
    • 2013-10-22
    • 2012-12-15
    • 1970-01-01
    • 1970-01-01
    • 2012-02-01
    • 1970-01-01
    相关资源
    最近更新 更多