我实施了一个基本计划(想想SICP)。现在,我想添加一个基本的导入/库功能,但是很难找到这样的方法。到目前为止,我考虑了两种方法,它们都面临着同样的障碍。
在旧的SICP (第一版)一书中,有一个制作环境/软件包的章节,其中也讨论了here。这将返回一个新的环境。
我想称之为
(import lib)其中lib要么提供环境,要么提供过程名称和过程的列表。我的问题是如何用库提供的过程以编程方式扩展当前环境。使用类似于
((lambda (name proc) (define name proc)) 'test (lambda a (+ a a)))由于define无法创建超出lambda范围的绑定,因此无法工作。
我已经看过r6rs的参考实现,但无法弄清楚import的底层机制是什么。它是如何创建绑定的?
更新1
我认为我所面临的基本问题(问题)是,不可能在define中使用lambda,因为通过define进行的环境修改仅限于周围lambda的范围。是否存在以编程方式define多个过程(例如生成)的原因。
这一工作(类似于所描述的here):
((eval `square-rrot scientific-lib) 4)还有这个
(eval `(square-rrot 4) scientific-lib)我甚至可以写
(define sqrt (eval `square-root scientific-lib))但是,上面的内容是不可持续的,如果我有一个包含100个函数的库,我不能一个一个地定义它们,我需要一个编程的方法来完成这个任务,但是我不能使用这样的方法:
((lambda (newName, libName) (define newName (eval libName scientific-lib))) sqrt `square-root)在我看来,在阅读了评论和答案后,它似乎不可能建立在SIPC中的内容上。一个人需要更高级的东西,比如define-syntax。还是我错了?
发布于 2014-12-28 09:03:36
最后我是怎么做到的。基本上,我脱离了计划,在lambda中添加了一个旗子。然后,λ可以被限定范围,也可以不限定作用域。范围内的lambda行为与通常的lambda一样。在这种情况下,lambda没有作用域,我在一个空的环境中评估身体。然后在当前环境中对此进行评估。就像这样:
if (lambdaHasAttribute(lambda, SCOPED)) {
eenv = environment_extend(parameter, arguments, lambda_env);
tmp = eval(lambda_body, eenv);
} else {
eenv = environment_extend(parameter, arguments, , mk_environment());
/* scope arguments */
tmp = eval(lambda_body, eenv);
/* evaluate unscoped */
tmp = eval(tmp, global_env);
}发布于 2014-11-23 01:19:58
因此,您的库只需要成为一堆具有本地环境的计算表单,就像定义中的那样。库产生的值将是添加到全局可用库列表中的某种对象,这些库具有名称及其值(过程、语法、.)。出口。
一个导入通常有大量的特性,但实际上它只接受一个库对象,并将它想要的绑定插入到一个框架中,并将程序/库的主体与该框架相结合。
您可以在Scheme中创建一个粗略的库实现,但是只要您不能轻松地更改环境框架,您就需要命名您需要导入的内容:
;; crude library support made with
;; syntax rules and closures
#!r6rs
(import (rnrs base)
(only (srfi :1) filter any))
(define-syntax lib
(syntax-rules ()
((_ name (export-symbols ...) body ...)
(define name
(let ()
; make the defines local
; here you import other libraries
body ...
;; ^binds is a assoc between symbols and
;; implementation.
(define ^binds
(list (cons 'export-symbols export-symbols) ...))
;; the function to leak definitions
(lambda args
(apply values
(map cdr
(filter
(lambda (x)
(any (lambda (e)
(eq? e (car x)))
args))
^binds)))))))))
(define-syntax imp
(syntax-rules ()
((_ name sym1)
(define sym1 (name 'sym1)))
((_ name symn ...)
(begin
(imp name symn) ...))))
;; test
(lib test (add sub)
(define (add a b)
(sub a (sub 0 b)))
(define (sub a b)
(- a b)))
(imp test add)
(add 5 3) ; ==> 8这看起来不太像,但是add使用来自同一个库的sub,因为我们没有导入它,所以这个库是全局不可用的。你看?您甚至还可以使用私有(而不是导出)过程。
它的主要工作是泄漏库表单创建的部分闭包的过程,这与消息传递背后的想法相同。(一种在计划中执行OOP的方法)
https://stackoverflow.com/questions/27067117
复制相似问题