Common Lisp中的函数名和动态绑定

时间:2013-08-20 09:38:04

标签: lisp eval common-lisp dynamic-binding

我正在阅读Peter Norvig的 范式。在第6.2章中,作者使用如下代码(不是原始代码,我选择了令人不安的部分):

代码段:

(progv '(op arg) '(1+ 1)
(eval '(op arg)))

作为作者的初衷,此代码应返回 2 ,但在sbcl 1.1.1中,解释器显然没有查找 op 在环境中,抛出op: undefined function

此实施是否具体?由于代码必须已在其他一些lisp上进行过测试。

p.s Original code

4 个答案:

答案 0 :(得分:5)

你可能意味着

(progv '(op arg) '(1+ 1)
  (eval '(funcall op arg)))

编辑(2013年8月21日):

PAIP是在ANSI-Common-Lisp之前的时代编写的,所以它可能是代码 标准中包含一些不符合项。我们可以做 这些示例使用以下修订版:

(defun match-if (pattern input bindings)
  "Test an arbitrary expression involving variables.
  The pattern looks like ((?if code) . rest)."
  (and (eval (reduce (lambda (code binding)
                       (destructuring-bind (var . val) binding
                         (subst val var code)))
                     bindings :initial-value (second (first pattern))))
       (pat-match (rest pattern) input bindings)))

;; CL-USER> (pat-match '(?x ?op ?y is ?z (?if (eql (?op ?x ?y) ?z))) '(3 + 4 is 7))
;; ((?Z . 7) (?Y . 4) (?OP . +) (?X . 3) (T . T))
;; CL-USER> (pat-match '(?x ?op ?y (?if (?op ?x ?y))) '(3 > 4))
;; NIL

答案 1 :(得分:3)

第一个位置的元素不会被查找为值,而是作为函数,函数名称空间中没有动态绑定的概念。

我会说快速查看原始代码是为了在

这样的上下文中进行评估
 (progv '(x y) '(12 34)
   (eval '(> (+ x y) 99)))

即。评估提供变量替换的公式,而不是函数名称。

答案 2 :(得分:2)

到目前为止的其他答案是正确的,因为正在评估的实际形式不是由progv(简称(op arg))约束的变量,但没有人提到被评估。实际上,您链接的代码中的注释提供了(非常)简短的解释(这是该文件中使用progv的唯一代码):

(defun match-if (pattern input bindings)
  "Test an arbitrary expression involving variables.
  The pattern looks like ((?if code) . rest)."
  ;; *** fix, rjf 10/1/92 (used to eval binding values)
  (and (progv (mapcar #'car bindings)
              (mapcar #'cdr bindings)
          (eval (second (first pattern))))
       (pat-match (rest pattern) input bindings)))

这个想法是调用match-if被称为

(match-if '((?if code) . rest) input ((v1 val1) (v2 val2) ...))
使用eval调用

(second (first pattern)),其值为code。但是,eval会在progv内将v1v2和c。绑定到相应的val1val2, & c。,这样如果这些变量中的任何一个在code中显示为空闲,那么在评估code时它们就会被绑定。

答案 3 :(得分:0)

问题

我在这里看到的问题是,通过代码我们无法判断该值是保存为变量symbol-value还是symbol-function。因此,当您将+作为值添加到某个对应变量时,比如说v,那么它总是会被保存为symbol-value的{​​{1}},而不是{&1;}} #39; s var
因此,当您尝试使用它时,比如说symbol-function,它就不会起作用。因为函数中没有名为(v 1 2)的函数'命名空间(见this)。

那么,该怎么办?

可能的解决方案可以是显式检查要绑定到变量的值。如果值是函数,那么它应该绑定到变量的函数值。此检查可以通过v完成。

因此,我们可以制作宏fboundpfunctioner的修改版本。 match-if检查值是否为函数,并适当地设置它。 functioner执行动态本地绑定,并允许绑定变量范围内的其他代码。

match-if