实现同步绑定

时间:2012-04-22 20:51:00

标签: lisp scheme

我正在编写一个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中实现同步绑定是否有规范方法?

2 个答案:

答案 0 :(得分:1)

SICP中,internal definitions部分介绍了此主题。特别是,练习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特殊表单。请查看链接的书籍以获取更多实施细节。

答案 1 :(得分:1)

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

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