java - 如何在 LISP 解释器中实现闭包

标签 java lisp closures interpreter

我目前正在研究用 Java 编写的 LISP 解释器。现在我坚持关闭。我想启用这样的闭包:

(define a 1000)
(define closure (lambda (a) (lambda (b) (+ a b))))
(define x (closure 10))
(x 20) --> 30

因此,(x 20) 应该返回 30。但是,你猜怎么着,它在我的解释器中返回 1020。我认为错误出在我的 lambda 类中。它看起来像这样:

public class LLambda extends LOperation {

    private LList parameters;
    private LList definitions;

    public LLambda(LList parameters, LList definitions) {

        this.parameters = parameters;
        this.definitions = definitions;
    } 

    public LObject eval(Environment environment, LObject tokens) {

        environment = environment.copy();

        for(int i = 0; i < parameters.size(); i++) {

            LSymbol key = LSymbol.create(parameters.get(i));
            LObject object = ((LList) tokens).get(i);
            object = object.eval(environment, tokens);  
            environment.put(key, object);
        }

        return definitions.eval(environment, tokens);
    }
}

这个类工作正常,但它不存储环境值来启用闭包。有人知道该怎么做吗?在哪里做?在构造函数中还是在 eval 方法中?

而且,如果我不执行此操作:

environment = environment.copy();

闭包有效,但它破坏了一些其他测试。

谢谢。

(我也可以上传整个源代码或在 GIT 中免费提供)。

最佳答案

此类工作正常,但它不存储环境值以启用闭包。有人知道该怎么做吗?在哪里做?在构造函数中还是在 eval 方法中?

是的,类应该存储环境。一般来说,一个成员变量。 :)

它应该在构造函数中,因为环境是在构造 lambda 时绑定(bind)的,而不是在 eval 时。

在评估时,原始环境不可用:新环境可用。

如果你的方言是纯词法范围的,那么你的 lambda 不需要环境参数。请记住,什么是 lambda?它是一个函数。 表单的评估需要一个环境。 函数的评估没有;函数的评估是一个函数调用,它只接受参数。环境不会传递给函数;函数体在具有自己私有(private)环境的封装空间中求值。 (在 lambda 上存在 eval 函数甚至看起来是错误的;您希望将其命名为 call 或类似的名称。解释的 lambda 使用 评估者的服务;但它不是一个。)

在您的 lambda 中,操作将是评估 lambda 主体的形式。这些将使用存储的环境(而不是传入的任何内容)。

您必须建立一个环境,让 lambda 参数绑定(bind)到参数值。这嵌套在捕获的环境中。 (即一个名为 x 的参数隐藏了一个名为 x 的捕获变量)。

(您必须已经有一些嵌套环境的方法;即构建一些引用外部环境的新绑定(bind)。)

如果除了词法之外还想支持动态作用域,则不需要为此传递环境;它可以隐式完成。线程局部变量可以维护动态环境或类似的东西。

(细节取决于解释器设计;在某些设计中,总是传递一些上下文对象(代表解释器)。如果你去,比如说,一个带有显式堆栈的字节码虚拟机,你将需要那个.)

关于java - 如何在 LISP 解释器中实现闭包,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10161802/

相关文章:

使用一个或两个参数进行闭包的常规方法

javascript - javascript中的关闭和回调内存泄漏

java - 如何在纸牌游戏中使用比较器

java - 什么是原始类型,为什么我们不应该使用它呢?

java - 是否可以使用 Smooks 或其他转换器进行 Java 对象到映射转换?

functional-programming - 方案尝试检查列表中的单词

reflection - 遍历 Scheme 函数作为列表

Java数组/逆新手

loops - 卡在 Clojure 循环中,需要一些指导

javascript - 这个 JavaScript 闭包函数如何重用没有全局变量的对象?