Programming languages 备忘录、解释器和闭包
所以我正在试验,并在scheme中创建了一种编程语言。我也为它构建了一个解释器,这是下面的大部分代码 我想重写解释器,以便它使用较小的环境构建闭包,即,在构建闭包时,它使用与当前环境类似的环境,但只保存闭包函数部分中的自由变量。我正在学习记忆,但这让人困惑 编辑:我现在使用的球拍相当于这个,所以如果那里比较容易,你应该给我一些建议Programming languages 备忘录、解释器和闭包,programming-languages,scheme,interpreter,memoization,Programming Languages,Scheme,Interpreter,Memoization,所以我正在试验,并在scheme中创建了一种编程语言。我也为它构建了一个解释器,这是下面的大部分代码 我想重写解释器,以便它使用较小的环境构建闭包,即,在构建闭包时,它使用与当前环境类似的环境,但只保存闭包函数部分中的自由变量。我正在学习记忆,但这让人困惑 编辑:我现在使用的球拍相当于这个,所以如果那里比较容易,你应该给我一些建议 (define-struct var (string)) ;; a variable, e.g., (make-var "foo") (define-struct i
(define-struct var (string)) ;; a variable, e.g., (make-var "foo")
(define-struct int (num)) ;; a constant number, e.g., (make-int 17)
(define-struct add (e1 e2)) ;; add two expressions
(define-struct fun (name formal body)) ;; a recursive 1-argument function
(define-struct closure (fun env)) ;; closures (made at run-time)
(define (envlookup env str)
(cond [(null? env) (error "unbound variable during evaluation" str)]
[(equal? (caar env) str) (cdar env)]
[#t (envlookup (cdr env) str)]))
(define (eval-prog p)
(letrec
([f (lambda (env p)
(cond [(var? p) (envlookup env (var-string p))]
[(int? p) p]
[(add? p) (let ([v1 (f env (add-e1 p))]
[v2 (f env (add-e2 p))])
(if (and (int? v1) (int? v2))
(make-int (+ (int-num v1) (int-num v2)))
(error "TTPL addition applied to non-number")))]
[(fun? p) (make-closure p env)]
[(closure? p) p]
[#t (error "bad TTPL expression")]))])
(f () p)))
如果您不介意阅读一些Haskell,可以演示如何创建闭包:当遇到
(lambda…
表达式时,它的闭包只需设置为当前环境(从名称到值的绑定列表)。当计算lambda时,其主体将在该闭包的上下文中加上参数绑定(当然不是当前环境)进行计算
听起来您想要做的是剔除成为闭包的环境,也许是为了提高效率。为此,您可以在函数中搜索名称,并仅保留参数列表中未显示的名称。但是,这可能会过多,因为lambda使用的每个名称(参数除外)都需要出现在闭包中。因此,我建议您只参考您已经拥有的环境,其中大部分都将被共享。第一个问题:您的语言中是否存在绑定变异?看起来您目前没有,但可能您正计划添加它。如果你这样做了,那么复制绑定就会打开一个新的蠕虫罐;需要额外的间接寻址 回答您的问题:是的,您当然可以做到这一点,大多数语言实现都可以做到。这与“空间安全”的特性有关,即闭包避免保留对大值的引用,否则可能会收集这些值 实现这一点非常简单:您可能希望通过在程序上进行单个静态传递,用其自由变量对每个表达式进行注释。在Racket中,我可能会构建一个哈希表,将表达式与其自由变量列表相关联
值得一提的是,我可以想象有七种方法,通过这样做,您可能会意外地使您的语言慢了一点:)。看起来您想要创建类似平面闭包的东西,或者Dybvig称之为“显示闭包”。也就是说,您必须递归地在lambda中找到自由变量,然后创建一个只包含这些自由变量的闭包表示 比如说,
((lambda (x) (lambda (f) (f x))) a)
将创建一个类似于[code,a]
的闭包
看看Dybvig的,第88页