制作未绑定变量列表(LISP)

时间:2012-02-19 23:37:06

标签: list lisp

我有以下LISP代码

(defun l (x y) (list x y))

当我(l a a)时,我收到A没有任何价值的错误。

我想要这个(a)。我怎么能克服这个?

2 个答案:

答案 0 :(得分:6)

我认为你的意思是你需要一个“符号”列表。当符号绑定到某个值时,它就变成了一个变量。您可以在将符号传递给l函数时“引用”符号来执行此操作:

(l 'a 'a)

推荐阅读:http://www.gigamonkeys.com/book/syntax-and-semantics.html

答案 1 :(得分:3)

答案

如果您对词法上下文有足够的宏扩展时间访问权限,以确定哪些变量是词法上未绑定的,那么您可以编写一个代码行走宏来用引号替换对未绑定变量的引用。通过一厢情愿的思维编程,宏看起来像下面这样:

(defmacro with-ad-hoc-quotations (&body forms &environment outer-env)
  (walk:map-variable-references
   (lambda (var env)
     (if (walk:lexically-bound-p var env)
         var
         `(if (boundp ',var)  ;deal with dynamic bindings
              (symbol-value ',var)
              ',var)))
   `(progn ,@forms)
   outer-env))

其中假定walk:map-variable-references是一个函数,它接受一个表单并将所提供的表单中的所有变量引用替换为将提供的函数应用于变量名和词法上下文的结果;并假设walk:lexically-bound-p返回一个通用布尔值,它告诉你给定的符号是否在给定的上下文中被词法绑定。

您需要自己发现后面函数的实现(并且walk:lexically-bound-p可能需要Lisp实现的支持),但这是一般的想法。宏的用法如下:

(with-ad-hoc-quotations (l a a))
;=> (A A)

或者,一个更有趣的例子,

(defvar *c* 20)

(with-ad-hoc-quotations
  (let ((b 10))
    (list a b *c*)))
;=> (A 10 20)

在SBCL中实施

作为概念验证,这是一个使用sb-walker的特定于SBCL的实现:

(defmacro with-ad-hoc-quotations (&body forms &environment outer-env)
  (sb-walker:walk-form
   `(progn ,@forms)
   outer-env
   (lambda (form ctx env)
     (declare (ignore ctx))
     (typecase form
       (symbol
        (if (sb-walker:var-lexical-p form env)
            form
            `(if (boundp ',form)
                 (symbol-value ',form)
                 ',form)))
       (t
        form)))))

或者,如果您更喜欢上述更通用的版本,我们可以按如下方式为SBCL实现两个必需的功能:

#+sbcl
(defun lexically-bound-p (var env)
  (sb-walker:var-lexical-p var env))

#+sbcl
(defun map-variable-references (fn form &optional env)
  (sb-walker:walk-form form
                       env
                       (lambda (expr ctx env)
                         (declare (ignore ctx))
                         (typecase expr
                           (symbol (funcall fn expr env))
                           (t      expr)))))

使用hu.dwim.walker

实施

最后,以下是基于可移植hu.dwim.walker库(可通过Quicklisp获得)的实现。请注意考虑封闭的词汇上下文,因此您通常需要在顶层调用它才能使其正常工作。

(defmacro with-ad-hoc-quotations (&body forms)
  (hu.dwim.walker:unwalk-form
   (hu.dwim.walker:rewrite-ast
    (hu.dwim.walker:walk-form `(progn ,@forms))
    (lambda (parent type form)
      (declare (ignore parent type))
      (typecase form
        (hu.dwim.walker:free-variable-reference-form
         (hu.dwim.walker:walk-form `',(hu.dwim.walker:name-of form)))
        (t
         form))))))