如何实现闭包到LISP解释器 [英] How to implement closures into a LISP interpreter

查看:153
本文介绍了如何实现闭包到LISP解释器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在编写一个用Java编写的LISP解释器。现在我停留在闭合。我要启用这样的闭包:

I'm currently working on a LISP interpreter written in Java. Now I stuck at the closures. I want to enable closures like this:

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

因此,(x 20) return 30 。但是,猜测什么,它在我的翻译中返回1020。我认为错误是在我的lambda类。它看起来像这样:

So, (x 20) should return 30. But, guess what, it returns 1020 in my interpreter. I think the mistake is in my lambda class. It looks like this:

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方法中?

This class works fine, but it doesn't stores the environment values to enable closures. Has someone an idea how to do it? And where to do it? In the constructor or in the eval method?

如果我不执行这个:

environment = environment.copy();

闭包可以工作,但会破坏一些其他测试。

The closures works, but it breaks some other tests.

感谢。

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

(I can also upload the whole source or give it free in GIT).

推荐答案

此类工作正常,但它不存储环境值以启用闭包。有人有个想法怎么办?和在哪里做呢?在构造函数或eval方法中?

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

Yes, the class should store the environment. Generally speaking, a member variable. :)

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

It should be in the constructor because the environment is bound at the time the lambda is constructed, and not at eval time.

在eval时,原始环境不可用:新环境是

At eval time, the original environment is not available: the new environment is.

如果你的方言纯粹是词法作用域,不需要环境参数。记住,什么是lambda?这是一个函数。评估形式需要一个环境。 的评估不会;函数的求值是一个函数调用,只需要参数。环境不传递函数;函数体在具有自己的私有环境的封装空间中进行评估。 (在lambda上存在一个 eval 函数似乎是错误的;你希望这个命名为 call 解释的lambda 使用评估程序的服务;但它不是一个。)

If your dialect is purely lexically scoped, then your lambda does not need an environment parameter. Remember, what is a lambda? It is a function. The evaluation of forms requires an environment. The evaluation of functions does not; the evaluation of a function is a function call, and that takes just arguments. Environments do not pass into functions; function bodies are evaluated in an encapsulated space with its own private environment. (The presence of an eval function on a lambda even seems wrong; you want this to be named call or something like that. The interpreted lambda uses the services of the evaluator; but it isn't one.)

以评估lambda主体的形式。那些将使用存储的环境(不是任何传递的)。

Inside your lambda, the action will be to evaluate the forms of the lambda body. Those will use the stored environment (not anything that was passed in).

您必须建立一个环境,其中lambda参数绑定到参数值。它嵌套在捕获的环境中。 (即一个名为 x 的参数阴影一个捕获的变量 x )。

You have to establish an environment in which the lambda parameters have bindings to the argument values. This is nested within the captured environment. (I.e. an argument called x shadows a captured variable called x).

(您必须已经有了一些嵌套环境;例如,构造一些引用外部环境的新绑定。)

(You must already have some way of nesting environments; i.e constructing some new bindings which refer to an outer environment.)

如果要支持动态范围除了词汇之外,不应该有任何需要为此传递一个环境;它可以隐式完成。线程局部变量可以维护动态环境或类似的东西。

If you want to support dynamic scoping in addition to lexical, there shouldn't be any need to pass an environment for that; it can be done implicitly. A thread-local variable can maintain the dynamic environment or something like that.

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

(The details depend on interpreter design; in some designs, there is always some context object passed around (representing the interpreter). If you go to, say, a byte code virtual machine with an explicit stack, you will need that.)

这篇关于如何实现闭包到LISP解释器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆