Emacs Lisp 提供了多种加载接口。例如,
autoload 会为文件中定义的函数创建一个占位对象;
调用这个自动加载函数时,会加载对应文件以获取函数的实际定义(see 自动加载)。
require 会在文件尚未加载时加载它(see 功能)。
最终,这些功能都会调用 load 函数来完成实际加载工作。
该函数查找并打开指定的 Lisp 代码文件,对其中所有表达式求值,然后关闭文件。
查找文件时,load 首先寻找名为
filename.elc 的文件(即文件名是 filename 附加扩展名 ‘.elc’)。
若该文件存在,且 Emacs 编译时启用了原生编译支持(see Lisp 本地代码编译),
load 会尝试查找对应的 ‘.eln’ 文件;
若找到,则加载该文件而非 filename.elc。
否则,加载 filename.elc(并在后台启动原生编译以生成缺失的 ‘.eln’ 文件,
编译完成后再加载该文件)。
若不存在 filename.elc,load 会查找名为 filename.el 的文件,
若存在则加载。
若 Emacs 编译时支持动态模块(see Emacs 动态模块),
load 接下来会查找名为 filename.ext 的文件,
其中 ext 是系统相关的共享库扩展名(GNU 和 Unix 系统上为 ‘.so’)。
最后,若以上文件名均未找到,load 会查找无任何后缀的 filename 文件,
若存在则加载。
(load 函数对 filename 的处理逻辑较为简单:
极端情况下,若存在名为 foo.el.el 的文件,执行 (load "foo.el") 确实会找到它。)
如果自动压缩模式(默认启用)处于开启状态,
当 load 找不到文件时,会先搜索该文件的压缩版本,再尝试其他文件名。
若找到压缩版本,则解压缩并加载。
它会通过将 jka-compr-load-suffixes 中的每个后缀附加到文件名后,
来查找压缩版本。
该变量的值必须是字符串列表,其标准值为 (".gz")。
若可选参数 nosuffix 非 nil,
则 load 不会尝试 ‘.elc’ 和 ‘.el’ 后缀。
此时你必须指定精确的文件名,但如果自动压缩模式开启,
load 仍会使用 jka-compr-load-suffixes 查找压缩版本。
通过指定精确文件名并将 nosuffix 设为 t,
可避免尝试 foo.el.el 这类文件名。
若可选参数 must-suffix 非 nil,
则 load 要求所用文件名必须以 ‘.el’、‘.elc’(可附加压缩后缀)
或共享库扩展名结尾,除非文件名中包含显式的目录名。
若选项 load-prefer-newer 非 nil,
则在搜索后缀时,load 会选择修改时间最新的文件版本(‘.elc’、‘.el’ 等)。
这种情况下,即使存在 ‘.eln’ 原生编译文件,load 也不会加载它。
若 filename 是相对文件名(如 foo 或 baz/foo.bar),
load 会通过变量 load-path 搜索文件。
它将 filename 附加到 load-path 列出的每个目录后,
加载第一个找到的匹配文件。
仅当当前默认目录在 load-path 中指定时(nil 代表默认目录),
才会尝试该目录。
load 会先在 load-path 的第一个目录中尝试所有三种可能的后缀,
再在第二个目录中尝试所有三种后缀,依此类推。See 库搜索。
无论最终找到的文件名和所在目录是什么,
Emacs 都会将变量 load-file-name 的值设为该文件的完整名称。
若收到警告提示 foo.elc 比 foo.el 旧, 说明你应考虑重新编译 foo.el。See 字节编译。
加载源文件(未编译)时,load 会执行字符集转换,
与 Emacs 访问该文件时的行为一致。See Coding Systems。
加载未编译文件时,Emacs 会尝试展开文件中包含的所有宏(see 宏)。 我们将此称为 立即宏展开(eager macro expansion)。 这种做法(而非延迟到相关代码运行时再展开) 能显著提升未编译代码的执行速度。 有时,由于循环依赖,宏展开无法完成。 最简单的例子是:你正在加载的文件引用了另一个文件中定义的宏, 而该文件又依赖于你正在加载的文件。 此时 Emacs 会抛出错误(提示 ‘因循环依赖跳过立即宏展开…’), 并给出问题详情。 你需要重构代码以避免这种情况。 加载编译文件不会触发宏展开,因为这一过程应已在编译时完成。See 宏与字节编译。
加载过程中,除非 nomessage 非 nil,
否则回显区会显示 ‘Loading foo...’ 和 ‘Loading foo...done’ 这类提示。
若加载的是原生编译的 ‘.eln’ 文件,提示信息会明确说明。
加载文件时出现的未处理错误会终止加载过程。
如果此次加载是因 autoload 触发,
加载过程中创建的所有函数定义都会被撤销。
若 load 找不到要加载的文件,通常会抛出 file-error 错误
(提示 ‘无法打开加载文件 filename’)。
但如果 missing-ok 非 nil,则 load 仅返回 nil。
你可以通过变量 load-read-function 指定一个函数,
让 load 用该函数替代 read 来读取表达式。
详见下文。
若文件加载成功,load 返回 t。
该命令加载文件 filename。
若 filename 是相对文件名,则使用当前默认目录。
该命令不使用 load-path,也不会附加后缀,
但会查找压缩版本(若自动压缩模式启用)。
如果你需要精确指定要加载的文件名,可使用此命令。
该命令加载名为 library 的库。
除了交互式读取参数的方式不同外,其功能与 load 等效。
See Lisp Libraries in The GNU Emacs Manual。
当 Emacs 正在加载文件时,该变量值为非 nil;否则为 nil。
当 Emacs 正在加载文件时,该变量的值是本节前文所述搜索过程中找到的文件名。
该变量为 load 和 eval-region 指定替代 read 的表达式读取函数。
该函数应像 read 一样接受一个参数。
默认情况下,该变量的值为 read。See 输入函数。
相比使用该变量,更规范的方式是使用一个更新的特性:
将该函数作为 read-function 参数传递给 eval-region。
See Eval。
关于 load 在 Emacs 构建过程中的使用方式,详见
Building Emacs。