2

我正在编写一个 Lisp(GitHub 上的代码),我想实现本地绑定。目前我有两种语法:

(let <var> <val> <expr>)

用于绑定单个变量或函数,以及

(with (<var1> <val1> ... <varN> <valN>) <expr>)

一次绑定多个值。

目前,绑定是按顺序评估的,每个新的函数绑定都保留了它定义的环境的副本,因此<var2>可以引用<var1>但反之不行。

我想修改代码,以便在一次绑定多个值时有效地同时绑定。例如,我希望能够编写(这是一个简单的例子,但它应该说明这个想法):

(define (h y)
  (with ((f x) (if (eq? x 0) #t (g (- x 1)))
         (g x) (if (eq? x 0) #f (f (- x 1))))
  (f y))

目前这段代码没有运行-g关闭f,但不是相反。

有没有一种规范的方法可以在 Lisp 中实现同时绑定?

4

2 回答 2

1

SICP中有一个关于内部定义的部分涵盖了这个主题。特别是,练习 4.16、4.18、4.19 告诉你如何实施不同的策略来实现同时定义。

语法有点不同,但书中的想法归结为转换这段代码:

(lambda <vars>
  (define u <e1>)
  (define v <e2>)
  <e3>)

进入这段代码:

(lambda <vars>
  (let ((u '*unassigned*)
        (v '*unassigned*))
    (set! u <e1>)
    (set! v <e2>)
    <e3>))

同样的想法也适用于您的with特殊形式。查看链接的书以了解更多实施细节。

于 2012-04-22T21:36:04.540 回答
1

(with (a (+ 2 2)))我们绑定a到表达式的值时(+ 2 2),soa变为 4。但是在(with ((f x) (+ x x)))我们正在做其他事情时:我们正在绑定f到一个函数。这是(with (f (lambda (x) (+ x x)))).

要处理这种情况,您必须分两次处理绑定。首先收集所有变量并创建包含所有变量的环境。然后评估初始化表达式并将它们的值存储在相应的变量中。这些表达式的评估发生那个环境中,因此每个表达式都可以看到所有变量。初始化是通过赋值完成的。变量可以是初始值,也可以nil具有一些陷阱值,如果它们被访问,就会爆炸。

于 2012-04-22T21:36:47.680 回答