方案R7RS中的负载与包含之间的差异 [英] Difference between load and include in Scheme R7RS

查看:54
本文介绍了方案R7RS中的负载与包含之间的差异的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在Scheme R7RS中,既有 load include 形式.

In Scheme R7RS there is both a load and include form.

包含被描述为:

语义:include和include-ci都取一个或将更多的文件名表示为字符串文字,请应用特定于实现的算法,查找对应的文件,读取以指定顺序显示文件内容,就像重复阅读应用,并有效地替换包含或include-ci表达式和包含已读内容的begin表达式从文件中.两者之间的区别在于include-ci读取每个文件,就好像它以#!fold-case指令开头,而包括不.注意:鼓励实施人员搜索目录中包含包含文件的文件,并且为用户提供一种指定其他目录进行搜索的方式.

Semantics: Both include and include-ci take one or more filenames expressed as string literals, apply an implementation-specific algorithm to find corresponding files, read the contents of the files in the specified order as if by repeated applications of read, and effectively re- place the include or include-ci expression with a begin expression containing what was read from the files. The difference between the two is that include-ci reads each file as if it began with the #!fold-case directive, while include does not. Note: Implementations are encouraged to search for files in the directory which contains the including file, and to provide a way for users to specify other directories to search.

负载描述为:

依赖于实现的操作用于转换文件名到包含Scheme源代码的现有文件的名称中.这加载过程从文件中读取表达式和定义,然后在指定的环境中顺序评估它们环境说明符.如果省略环境说明符,假设为(互动环境).未指定是否表达式的结果被打印出来.加载过程不影响current-input-port和当前输出端口.它返回一个未指定的值.理由:对于可移植性,加载必须在源文件上进行.其对其他的操作各种实现中的文件类型必然有所不同.

An implementation-dependent operation is used to trans- form filename into the name of an existing file con- taining Scheme source code. The load procedure reads expressions and definitions from the file and evalu- ates them sequentially in the environment specified by environment-specifier. If environment-specifier is omitted, (interaction-environment) is assumed. It is unspecified whether the results of the expres- sions are printed. The load procedure does not af- fect the values returned by current-input-port and current-output-port. It returns an unspecified value. Rationale: For portability, load must operate on source files. Its operation on other kinds of files necessarily varies among implementations.

这两种形式的基本原理是什么?我认为这是历史性的.两种形式之间在导入语义上有什么区别吗?我看到 load 可以选择包含一个环境说明符,而 include 则没有.并且 include-ci 在使用 load 时没有直接等效项.但是,仅将 load include 进行比较,有什么区别,并且重要吗?

What is the rationale for the two forms? I assume it is historic. Is there any import semantic difference between the two forms? I see that load can optionally include an environment specifier and include doesn't have that. And include-ci has no direct equivalent using load. But comparing load and include alone, what is the difference and is it important?

推荐答案

我认为关键的区别是 include 语法(或者在传统的Lisp术语中,它是一个宏),而 load 是一个函数.用传统的Lisp术语(在Scheme术语中会有一个更正式的定义,我无法胜任),这意味着 include 在宏扩展时起作用,而load 在评估时完成工作.对于具有文件编译器的实现,这些时间可能会非常不同:宏扩展时间发生在文件编译期间,而评估仅发生在加载编译后的文件之后很多.

I think the critical difference is that include is syntax (or in traditional Lisp terms, it is a macro) while load is a function. In traditional Lisp terms (there will be a much more formal definition of this in Scheme terms which I am not competent to give) this means that include does its work at macro-expansion time, while load does its work at evaluation time. These times can be very different for an implementation which has a file compiler: macro-expansion time happens during compilation of files, while evaluation happens only much later, when the compiled files are loaded.

因此,如果我们考虑两个文件,其中 f1.scm 包含

So, if we consider two files, f1.scm containing

(define foo 1)
(include "f2.scm")

f2.scm 包含

(define bar 2)

然后,如果您加载,或编译 f1.scm ,则与加载或编译文件 fe.scm 完全相同>其中包含:

then if you load, or compile f1.scm it is exactly the same as if you had loaded or compiled a file fe.scm which contained:

(define foo 1)
(begin
  (define bar 2))

反过来与 fe.scm 包含的内容相同:

which in turn is the same as if fe.scm contained:

(define foo 1)
(define bar 2)

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

In particular this inclusion of the files happens at macro-expansion time, which happens when the compiler runs: the object file (fasl file) produced by the compiler will include compiled definitions of foo and bar, and will not in any way depend on f2.scm or its compiled equivalent existing.

现在考虑包含以下内容的 f3.scm

Now consider f3.scm containing:

(define foo 1)
(load "f2")

(请注意,我假设(加载"f2")(而不是(加载"f2.scm"))可以加载已编译的文件它,以及源文件(如果不能):我认为这与实现有关).

(note I have assumed that (load "f2") (as opposed to (load "f2.scm")) loads the compiled file if it can find it, and the source file if it can't: I think this is implementation-dependent).

加载此文件的源代码将与加载 f1.scm 相同:将导致定义 foo bar .但是 compiling 该文件不会:它将生成一个已编译的文件,该文件在以后加载时会 尝试加载 f2的源版本或编译版本.scm .如果该文件存在,则在加载时将被加载,其效果将与 include 情况相同.如果它在加载时不存在,则会发生不良情况.编译 f1.scm 不会导致 f2.scm 中的定义被编译.

Loading the source of this file will do the same thing as loading f1.scm: it will cause foo and bar to be defined. But compiling this file will not: it will produce a compiled file which, when it is later loaded will try to load either the source or compiled versions of f2.scm. If that file exists, at load time, then it will be loaded and the effect will be the same as the include case. If it does not exist at load time, bad things will happen. Compiling f1.scm will not cause the definitions in f2.scm to be compiled.

根据您的背景,可能需要将其与C族语言进行比较. include 的作用是 #include 的作用:它在读取时在源文件中进行拼接,而在C中(如在许多Scheme/Lisp系统中)则在文件中发生被编译. load 的作用是在运行时加载代码 ,这在C语言中,您需要通过调用动态链接程序或其他方式来完成.

Depending on your background it might be worth comparing this to, say, C-family languages. What include does is what #include does: it splices in source files as they are read, and in C (as in many Scheme/Lisp systems) this happens as the files are compiled. What load does is to load code at runtime, which, in C, you would need to do by invoking the dynamic linker or something.

这篇关于方案R7RS中的负载与包含之间的差异的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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