Scheme 方案R7RS中负载和包含之间的差异

Scheme 方案R7RS中负载和包含之间的差异,scheme,lisp,r7rs,Scheme,Lisp,R7rs,在方案R7RS中,有一个加载和包含表单 包括如下所述: 语义:include和include ci都取一个或多个 更多以字符串文字表示的文件名,请应用 实现特定算法,查找相应文件,读取 文件的内容按指定的顺序重复 应用程序读取,并有效地重新放置包含或 包含ci表达式和包含读取内容的begin表达式 从档案中。两者之间的区别在于包括ci 读取每个文件,就像它以#开头一样!折叠case指令,而 包括但不包括。注意:鼓励实现搜索 包含包含文件的目录中的文件,以及 为用户指定要搜索的其他目录提供一种方法

在方案R7RS中,有一个
加载
包含
表单

包括如下所述:

语义:include和include ci都取一个或多个 更多以字符串文字表示的文件名,请应用 实现特定算法,查找相应文件,读取 文件的内容按指定的顺序重复 应用程序读取,并有效地重新放置包含或 包含ci表达式和包含读取内容的begin表达式 从档案中。两者之间的区别在于包括ci 读取每个文件,就像它以#开头一样!折叠case指令,而 包括但不包括。注意:鼓励实现搜索 包含包含文件的目录中的文件,以及 为用户指定要搜索的其他目录提供一种方法

负载描述为:

依赖于实现的操作用于转换文件名 输入包含方案源代码的现有文件的名称。这个 加载过程从文件中读取表达式和定义,然后 在指定的环境中按顺序评估它们 环境说明符。如果省略了环境说明符, (交互环境)是假定的。目前尚不清楚 将打印表达式的结果。加载过程不可用 af-验证当前输入端口返回的值,并 电流输出端口。它返回一个未指定的值。理由:为了 可移植性、加载必须对源文件进行操作。它在其他方面的运作 文件的种类在不同的实现中必然有所不同


这两种形式的基本原理是什么?我认为这是历史性的。这两种形式在语义上有什么区别吗?我看到
load
可以选择包含环境说明符,而
include
没有环境说明符。而
include ci
在使用
load
时没有直接等价物。但是,单独比较
load
include
有什么区别,它重要吗?

历史上,Lisp实现没有提供模块系统

大型程序使用load为了运行一组指令,load函数通过逐个读取文件中的S表达式并将其传递给eval来运行REPL脚本

另一方面,Include用于将从文件读取的代码内联到代码中。它不计算代码。

…将包含或包含ci表达式替换为包含从文件中读取内容的begin表达式

添加的“开始”准备从文件中读取的代码,以便按顺序计算。


资料来源:问题引语,

我认为关键的区别在于
包含
是语法(或者在传统的Lisp术语中,它是一个宏),而
加载
是一个函数。在传统的Lisp术语中(在Scheme术语中会有一个更正式的定义,我无法给出),这意味着
include
在宏扩展时工作,而
load
在计算时工作。对于具有文件编译器的实现来说,这些时间可能非常不同:宏扩展时间发生在文件编译期间,而计算只在编译后的文件加载时发生

这样,如果我们考虑两个文件,<代码> f1.SCM包含

(define foo 1)
(include "f2.scm")
(define bar 2)
f2.scm
包含

(define foo 1)
(include "f2.scm")
(define bar 2)
然后,如果加载或编译
f1.scm
,则与加载或编译包含以下内容的文件
fe.scm
完全相同:

(define foo 1)
(begin
  (define bar 2))
(define foo 1)
(define bar 2)
而这又与fe相同。scm包含:

(define foo 1)
(begin
  (define bar 2))
(define foo 1)
(define bar 2)
尤其是在宏扩展时(编译器运行时)包含文件:编译器生成的目标文件(fasl文件)将包含
foo
bar
的编译定义,并且不会以任何方式依赖于
f2.scm
或其已编译的等效文件

现在考虑<代码> f3,SCM包含:

(define foo 1)
(load "f2")
(注意,我假设
(load“f2”)
(与
(load“f2.scm”)
)相反,如果可以找到编译后的文件,则加载它;如果找不到,则加载源文件:我认为这取决于实现)

加载此文件的源代码将执行与加载
f1.scm
相同的操作:它将导致定义
foo
bar
。但编译此文件不会:它将生成一个编译文件,稍后加载时,该文件将尝试加载
f2.scm
的源版本或编译版本。如果该文件在加载时存在,则将加载该文件,其效果将与
include
案例相同。如果它在加载时不存在,则会发生不好的事情。编译
f1.scm
不会导致编译
f2.scm
中的定义


根据您的背景,可能值得将其与C族语言进行比较。
include
所做的就是
#include
所做的:它在读取源文件时在源文件中拼接,而在C语言中(就像在许多Scheme/Lisp系统中一样),这是在编译文件时发生的。
load
所做的是在运行时加载代码,在C语言中,您需要调用动态链接器或其他方法来完成这项工作