Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/396.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何在LISP解释器中实现闭包_Java_Lisp_Closures_Interpreter - Fatal编程技术网

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

Java 如何在LISP解释器中实现闭包,java,lisp,closures,interpreter,Java,Lisp,Closures,Interpreter,我目前正在开发一个用Java编写的LISP解释器。现在,我坚持关闭。我想启用如下闭包: (define a 1000) (define closure (lambda (a) (lambda (b) (+ a b)))) (define x (closure 10)) (x 20) --> 30 public class LLambda extends LOperation { private LList parameters; private LList defini

我目前正在开发一个用Java编写的LISP解释器。现在,我坚持关闭。我想启用如下闭包:

(define a 1000)
(define closure (lambda (a) (lambda (b) (+ a b))))
(define x (closure 10))
(x 20) --> 30
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);
    }
}
因此,
(x20)
应该返回
30
。但是,猜猜看,我的解释器返回1020。我想错误出在我的lambda课上。看起来是这样的:

(define a 1000)
(define closure (lambda (a) (lambda (b) (+ a b))))
(define x (closure 10))
(x 20) --> 30
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);
    }
}
闭包可以工作,但它破坏了其他一些测试

谢谢


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

我强烈建议阅读Christian Queinnec的书,书中详细描述了实现Lisp(或类似Scheme的)计算器、解释器和编译器的许多方法

您需要处理不同于本地值的闭合值。

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

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

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

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

如果您的方言是纯词汇范围的,那么您的lambda不需要环境参数。记住,什么是lambda?这是一个函数。表单的评估需要一个环境。对功能的评估不适用;函数的求值是函数调用,它只接受参数。环境不会转化为功能;功能体在一个具有自己的私有环境的封装空间中进行评估。(lambda上存在
eval
函数似乎是错误的;您希望将其命名为
call
或类似的名称。解释的lambda使用计算器的服务;但它不是。)

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

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

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

如果您想在词法之外支持动态范围,那么不需要为此传递环境;它可以隐式地完成。线程局部变量可以维护动态环境或类似的东西


(细节取决于解释器的设计;在某些设计中,总是会传递一些上下文对象(表示解释器)。如果您转到(比如)具有显式堆栈的字节码虚拟机,您将需要它。)

闭包(根据定义)为了包含闭包值,我对1998年版本的JScheme进行了mavenized,它可以实现闭包。你可能想看看@Thorbjørn Ravn Andersen上的代码,这真是太棒了!