Clojure 在Lisp中,表单和文件之间的关系是什么?
我在理解Lisp的过程中遇到了一个小问题。根据公共Lisp标准,表单是一个原子或列表,用于计算。这似乎很容易 在现实世界中,目前,我们将程序存储在文件中。SBCL、Clojure等都有一个文件的概念,也可以对其进行评估 这是如何理解的?文件最终是否被视为要评估的单个表单,它是表单的集合?出于某种原因,这让我很困惑。根据:Clojure 在Lisp中,表单和文件之间的关系是什么?,clojure,lisp,common-lisp,Clojure,Lisp,Common Lisp,我在理解Lisp的过程中遇到了一个小问题。根据公共Lisp标准,表单是一个原子或列表,用于计算。这似乎很容易 在现实世界中,目前,我们将程序存储在文件中。SBCL、Clojure等都有一个文件的概念,也可以对其进行评估 这是如何理解的?文件最终是否被视为要评估的单个表单,它是表单的集合?出于某种原因,这让我很困惑。根据: 这意味着文件是一系列表单。文件是存储表单的地方。打开文件(使用OPEN或with-OPEN-file)会提供一个流,READ函数可以将表单从流中读取到可以计算或编译的对象中 在
这意味着文件是一系列表单。文件是存储表单的地方。打开文件(使用
OPEN
或with-OPEN-file
)会提供一个流,READ
函数可以将表单从流中读取到可以计算或编译的对象中
在Common Lisp中,重要的是要认识到程序的语义是在读取的对象上定义的,而不是在文件中存储的文本上定义的
可能有助于从编译的角度理解它
谈论负载
我在理解Lisp的过程中遇到了一个小问题。根据公共Lisp标准,表单是一个原子或列表,用于计算。这似乎很容易
请注意,这基本上是基于数据的EVAL
将表单作为数据,而不是文本作为其求值参数。我们必须先阅读文本,才能为EVAL
创建一个表单。如果我们谈论文件中的表单,这基本上是从文件中读取表单的简写
在现实世界中,目前,我们将程序存储在文件中。SBCL、Clojure等都有一个文件的概念,也可以对其进行评估
公共Lisp是现实世界的一部分。代码主要存储在文本文件中。不一定如此,但事实就是如此。这就是为什么Common Lisp具有诸如OPEN
、WITH-OPEN-FILE
、READ
、LOAD
、COMPILE-FILE
等功能
否,无法“计算”Lisp中的文件EVAL
是求值器,它将Lisp表单作为参数,而不是文件。在Lisp中,可以加载文件。加载文件意味着:打开文件进行读取,从文件中读取,并逐个表单评估表单
在普通情况下,还可以编译Lisp文件以创建“fasl”(快速加载)文件。对于类似SBCL的内容,此文件将包含机器代码和数据。也可以加载此文件。加载将逐个为每个表单执行生成的代码
因此,Common Lisp可以加载两种类型的文件:带有Lisp代码的文本文件和带有编译代码的FASL文件
您还可以打开一个文本文件进行阅读,使用Lisp reader阅读表单,并根据需要对结果执行任何操作。您还可以打开文本文件进行写入,并将Lisp表单作为文本写入该文件
在Lisp中,将源代码存储在文件中是常见的做法
这方面也有例外:
- 大多数常见的Lisp实现(并非全部)都允许我们保存图像。该映像是正在运行的Lisp系统的当前内存状态的转储。因此,您可以在运行的程序中将Lisp表单作为数据,然后转储映像,然后重新启动映像。重新启动的映像仍将包含所有数据,这意味着作为数据存储的代码也将仍然存在
- 类似Interlisp-D的东西,一个不再广泛使用的Lisp系统,也有一个通用的Lisp实现。INTERISP-D将源代码存储在程序控制下的文本文件中。因此,文本文件的使用更像一个数据库
- 一些Lisp系统也支持自动加载。调用一个函数,该函数未知,然后它在其他地方(数据库、源代码)查找源代码,加载它,然后重试调用现在已知的函数。通过这种方式,用户无需加载文件,Lisp系统会在后台进行加载。在早期的Lisp系统中,自动加载用于节省主内存中的空间,而不是同时加载所有内容。即使是较新的Lisp实现也可能会对某些功能使用某种形式的自动加载
load sequentially executes each form it encounters in the file
named by filespec