18.1 Running Racket or GRacket
核心的 Racket 运行时系统有两种主要变体:
Racket,它提供了实现 racket/base 所依赖的基础库。在 Unix 和 Mac OS 上,可执行文件名为 racket. On Windows, the executable is called Racket.exe.
GRacket,它是 racket 的一个 GUI 变体,其程度取决于系统对它们的区分。在 Unix 上,可执行文件名为 gracket, 和 single-instance 标志 和 X11 相关标志专门处理并传递给 the racket/gui/base library. On Windows, the executable is called GRacket.exe, and it is a GUI application (as opposed to a console application) that implements single-instance support. On Mac OS, the gracket script launches GRacket.app.
18.1.1 Initialization
在启动时,顶级环境不包含任何 binding——甚至连 #%app for function application. 名称以 #% 开头的原始 module 已被定义,但它们不用于直接使用,且此类 module 的集合可能会变化。 For example, the '#%kernel module is eventually used to bootstrap the implementation of racket/base.
Racket 或 GRacket 的第一个动作是 current-library-collection-paths 设置为 (find-library-collection-paths pre-extras extras) 的结果,其中 pre-extras 通常为 null,extras 是命令行通过 -S/--search 指定的额外目录路径。 由 Racket 或 GRacket 可执行文件生成的独立执行文件 可以嵌入将作为 pre-extras 使用的路径。
Racket 和 GRacket 接着 require racket/init and racket/gui/init, respectively, but only if the command line does not specify a require flag (-t/--require, -l/--lib, or -u/--require-script) before any eval, load, or read-eval-print-loop flag (-e/--eval, -f/--load, -r/--script, -m/--main, or -i/--repl). The initialization library can be changed with the -I configuration option. The 初始化库的 configure-runtime submodule 或初始化库语言的 'configure-runtime property 在库被实例化之前使用;参见 Language Run-Time Configuration。
在可能加载初始化模块之后, eval、load 和 require 按命令行提供的顺序执行。如果其中任何一个引发了未捕获的异常,则跳过剩余的 eval、load 和 require。如果第一个 require 先于任何 eval 或 load,从而使初始化库被跳过,则被 require 的 module 的 configure-runtime submodule 或 被 require 的 module 的库语言的 'configure-runtime property 在 module 被实例化之前使用;参见 Language Run-Time Configuration。
在运行所有命令行 expression、, 和 module 之后,如果没有提供除 configuration option 之外的命令行标志,Racket 或 GRacket 会启动一个 read-eval-print loop 进行交互式求值。对于 Racket,read-eval-print loop 通过调用 racket/repl 中的 read-eval-print-loop 来运行。对于 GRacket,read-eval-print loop 通过调用 racket/gui/base 中的 graphical-read-eval-print-loop 来运行。如果提供了不是 configuration option 的任何命令行参数,则不会启动 read-eval-print-loop,除非在命令行上提供了 -i/--repl 标志来专门重新启用它。
此外,在 read-eval-print loop 即将启动之前 之前,Racket 运行 racket/interactive,GRacket 运行 racket/gui/interactive,除非在 (find-config-dir) 中找到的安装的 "config.rktd" 文件中指定了不同的交互文件,或者在 (find-system-path 'addon-dir) 中找到了 "interactive.rkt" 文件。如果在命令行上指定了 -q/--no-init-file 标志,则不运行任何交互文件。
最后,在 Racket 或 GRacket 退出之前, 它会调用主线程中 executable-yield-handler 当前值的 procedure,除非指定了 -V/--no-yield 命令行标志。require racket/gui/base 会设置此 parameter 调用 (racket 'yield)。
Changed in version 6.7 of package base: Run racket/interactive file
rather than directly running (find-system-path 'init-file).
Changed in version 6.90.0.30: Run a read-eval-print loop by
using racket/repl or racket/gui/base
instead of racket/base or racket/gui/init.
18.1.2 Exit Status
如果在命令行期间发生错误,则 Racket 或 GRacket 进程 if 如果在命令行 eval(通过 -e 等)、load(通过 -f、-r 等)或 require(通过 -l、-t 等)期间发生错误——或者更一般地,如果围绕这些求值的 prompt 的 abort handler 被调用——但仅当没有启动 read-eval-print loop 时才会。否则,默认退出状态为 0。
在所有情况下,对 exit (when the default exit handler is in place) can end the process with a specific status value.
18.1.3 Init Libraries
| (require racket/init) | package: base |
| (require racket/interactive) | package: base |
Added in version 6.7 of package base.
| (require racket/language-info) | package: base |
See also (part ("(lib scribblings/guide/guide.scrbl)" "module-runtime-config")) in (part ("(lib scribblings/guide/guide.scrbl)" "top")).
矢量 '#(racket/language-info get-info #f) 适合 附加到模块作为其 language info,以获取与 racket/base 语言相同的语言信息。
| (require racket/runtime-config) | package: base |
矢量 #(racket/runtime-config configure #f) 适合 作为运行时配置规范列表中的一个成员(由模块的 language-information 函数为键 'configure-runtime 返回),以获得与 racket/base 语言相同的运行时配置。
18.1.4 Command Line
Racket 和 GRacket 可执行文件识别以下 command-line flags:
文件和 expression 选项:
-e ‹expr› or --eval ‹expr› : eval ‹expr›。求值结果通过 current-print 打印。
-f ‹file› or --load ‹file› : load ‹file›;如果 ‹file› 是 "-",则从标准输入读取并求值 expression。
-t ‹file› or --require ‹file› : require ‹file›,如果可用,然后 require (submod (file "‹file›") main)。
-l ‹path› or --lib ‹path› : require (lib "‹path›"),如果可用,然后 require (submod (lib "‹path›") main)。
-p ‹package› : require (planet "‹package›"),如果可用,然后 require (submod (planet "‹package›") main)。
-r ‹file› or --script ‹file› : load ‹file› 尽管名为 --script,它通常不用于 Unix 脚本。有关脚本的更多信息,参见 (part ("(lib scribblings/guide/guide.scrbl)" "scripts"))。 作为脚本。此标志类似于 -f ‹file› 加上 -N ‹file› 来设置程序名和 -- 来使所有后续命令行元素被视为非标志参数。
-u ‹file› or --require-script ‹file› : requires ‹file› as a script; 此标志类似于 -t ‹file› plus -N ‹file› 来设置程序名和 -- to cause all further command-line elements to be treated as non-flag arguments.
-k ‹n› ‹m› ‹p› : 从可执行文件中的文件位置 ‹n› 到 ‹m› 以及从 ‹m› 到 ‹p› 加载嵌入的代码。(在 Mac OS 上,‹n›、‹m› 和 ‹p› 相对于可执行文件中的 __PLTSCHEME 段。在 Windows 上,它们相对于类型 257、ID 1 的资源。在使用 ELF 的 Unix 上,它们相对于可执行文件中的 .rackprog 段。)第一个范围在每个新的 place 中加载,在该范围中声明的任何 module 在 module-predefined? 的意义上被认为是预定义的。此选项通常嵌入在也嵌入了 Racket 代码的独立二进制文件中。
-Y ‹file› ‹n› ‹m› ‹p› : 类似于 -k ‹n› ‹m› ‹p›,但从 ‹file› 读取(不需要对段或资源偏移进行调整)。
-m or --main : 求值对在顶层环境中绑定的 main 的调用。所有未被作为选项处理的命令行参数(即放入 current-command-line-arguments 的参数)作为参数传递给 main。调用结果通过 current-print 打印。
对 main 的调用被构造为 expression (main arg-str ...),其中 expression 的词法上下文将 #%app 和 #%datum 绑定为 #%plain-app 和 #%datum,但 main 的词法上下文是顶层环境。
交互选项:
-i or --repl : 运行交互式 read-eval-print loop,在显示 (banner) 并加载 (find-system-path 'init-file) 之后,使用 read-eval-print-loop(Racket)或 graphical-read-eval-print-loop(GRacket)。对于 Racket,(read-eval-print-loop) 之后跟随 (newline)。对于 GRacket,提供 -z/--text-repl configuration option 以使用 read-eval-print-loop(和 newline)代替 graphical-read-eval-print-loop。
-n or --no-lib : 在未被其他方式禁用时,跳过 require 初始化库(即 racket/init 或 racket/gui/init,除非通过 -I 标志更改)。
-v or --version : 显示 (banner)。
-V --no-yield : 跳过最终的 executable-yield-handler 操作,该操作通常在使用 racket/gui/base 的程序退出之前等待主 eventspace 中的所有帧关闭等。出于历史原因,此标志也隐含 -v, 这使得它不太有用,但意味着 -V by itself behaves like -v by iself.
-y or --make : 启用在初始 namespace 中加载的 module 的已编译 ".zo" 文件的自动生成和更新。具体来说,(make-compilation-manager-load/use-compiled-handler) 的结果在其他 module 加载操作之前被安装为 compiled-load handler。注意:此标志用于交互式环境;在脚本中使用它可能是个坏主意,因为脚本的并发调用可能会在尝试更新已编译文件时冲突,或者可能存在文件系统权限问题。使用 -c/--no-compiled 取消 -y/--make 的效果。
-c or --no-compiled : 通过将 use-compiled-file-paths 初始化为 null 来禁用加载已编译的 ".zo" 文件。请谨慎使用:这实际上忽略了所有 "compiled" 子目录的内容,使得任何使用的 module 都会即时编译——包括 racket/base 及其依赖——这会导致极其昂贵的运行时间。
-q or --no-init-file : 对于 -i/--repl,跳过加载 (find-system-path 'init-file)。
-z or --text-repl : 仅限 GRacket;将 -i/--repl 改为使用 textual-read-eval-print-loop 代替 graphical-read-eval-print-loop。
-I ‹path› : 将 (lib "‹path›") 设置为用于初始化 namespace 的 require 路径,除非 namespace 初始化被禁用。使用此标志可以有效设置 read-eval-print loop 和其他顶层求值的语言。
-X ‹dir› or --collects ‹dir› : 通过使 (find-system-path 'collects-dir) 产生 ‹dir›,将 ‹dir› 设置为主要库集合的路径。如果 ‹dir› 是空字符串,则 (find-system-path 'collects-dir) 返回 ".",但 current-library-collection-paths 被初始化为空列表,use-collection-link-paths 被初始化为 #f。
-S ‹dir› or --search ‹dir› : 将 ‹dir› 添加到主集合目录之后的默认库集合搜索路径中。如果多次提供 -S/--dir 标志,搜索顺序按提供顺序排列。
-G ‹dir› or --config ‹dir› : 设置 (find-system-path 'config-dir) 返回的目录。
-A ‹dir› or --addon ‹dir› : 设置 (find-system-path 'addon-dir) 返回的目录。
-U or --no-user-path : 通过将 use-user-specific-search-paths parameter 初始化为 #f,在搜索集合、C 库等时省略用户特定路径。
-A ‹dir› or --addon ‹dir› : 设置 (find-system-path 'addon-dir) 返回的目录。
-R ‹paths› or --compiled ‹paths› : 设置 current-compiled-file-roots parameter 的初始值,覆盖任何 PLTCOMPILEDROOTS 设置。‹paths› 参数的解析方式与 PLTCOMPILEDROOTS 相同(参见 current-compiled-file-roots)。
-C or --cross : 选择跨平台构建模式,使 (system-type 'cross) 报告 'force,并将 (find-system-path 'config-dir)、(find-system-path 'collects-dir) 和 (find-system-path 'addon-dir) 的当前配置分别设置为 (find-system-path 'host-config-dir)、(find-system-path 'host-collects-dir) 和 (find-system-path 'host-addon-dir) 的结果。如果多次提供 -C 或 --cross,只有第一个实例生效。
-N ‹file› or --name ‹file› : 将 (find-system-path 'run-file) 报告的可执行文件名称设置为 ‹file›。
-E ‹file› or --exe ‹file› : 将 (find-system-path 'exec-file) 报告的可执行文件名称设置为 ‹file›。
-J ‹name› or --wm-class ‹name› : 仅限 Unix 上的 GRacket;将 WM_CLASS 程序类设置为 ‹name›(而 WM_CLASS 程序名从可执行文件名称或 -N/--name 参数派生)。
-j or --no-jit : 通过将 eval-jit-enabled parameter 设置为 #f 来禁用本地代码即时编译器。
-M or --compile-any : 通过将 current-compile-target-machine parameter 设置为 #f 来启用与机器无关的字节码。
-d or --no-delay : 通过将 read-on-demand-source parameter 设置为 #f 来禁用已编译代码和 syntax object 的按需解析。
-b or --binary : 为进程的输入、输出和错误端口请求二进制模式而非文本模式。此标志目前没有效果,因为始终使用二进制模式。
-W ‹levels› or --warn ‹levels› : 设置将事件写入原始错误端口的日志级别。可能的 ‹level› 值与 PLTSTDERR 环境变量相同。更多信息参见 Logging。
-O ‹levels› or --stdout ‹levels› : 设置将事件写入原始输出端口的日志级别。可能的 ‹level› 值与 PLTSTDOUT 环境变量相同。更多信息参见 Logging。
-L ‹levels› or --syslog ‹levels› : 设置将事件写入系统日志的日志级别。可能的 ‹level› 值与 PLTSYSLOG 环境变量相同。更多信息参见 Logging。
元选项:
如果至少提供了一个命令行参数, 并且如果任何 configuration option 之后的第一个参数不是标志,则在第一个非标志参数之前隐式添加 -u/--require-script 标志。
除了配置选项外没有提供其他命令行参数 configuration options, then the -i/--repl flag is effectively added.
对于 Unix 上的 GRacket, 以下标志在出现在命令行开头时被识别,并且被视为 configuration option(即它们不会禁用 read-eval-print loop 或阻止插入 -u/--require-script):
-geometry ‹arg›, -bg ‹arg›, -background ‹arg›, -fg ‹arg›, -foreground ‹arg›, -fn ‹arg›, -font ‹arg›, -iconic, -name ‹arg›, -rv, -reverse, +rv, -selectionTimeout ‹arg›, -synchronous, -title ‹arg›, -xnllanguage ‹arg›, or -xrm ‹arg› : 标准 X11 参数,大多数被忽略,但为了与其他 X11 程序兼容而被接受。-synchronous 标志以通常的方式运行。
-singleInstance : 如果已有一个现有的 GRacket 在同一 X11 display 上运行,且是在具有相同主机名的机器上启动的,并且启动时使用的名称与 (find-system-path 'run-file) 报告的名称相同——可能通过 -N/--name 命令行参数设置——则所有非选项命令行参数被视为文件名,并通过 application file handler 发送给现有的 GRacket 实例(参见 application-file-handler)。
类似地,在 Mac OS 上, 开头为 -psn_ 的开关被视为特殊配置选项。 它表示 Finder 启动了该应用,因此当前输入、输出和错误输出 被重定向到 GUI 窗口。
多个单字母开关 (前面只有一个 - 的那些)可以通过连接字母合并为一个开关,只要第一个开关不是 --。每个开关的参数放在合并后的开关之后(按开关的顺序)。例如,
-ifve ‹file› ‹expr›
and
-i -f ‹file› -v -e ‹expr›
是等价的。如果合并的 -- 出现在同一合并集中的其他合并开关之前,则隐式地移至合并集的末尾。
最后一个选项之后的额外参数 可从 current-command-line-arguments parameter 获取。
Changed in version 6.90.0.17 of package base: Added -O/--stdout.
Changed in version 7.1.0.5: Added -M/--compile-any.
Changed in version 7.8.0.6: Added -Z.
Changed in version 8.0.0.10: Added -E.
Changed in version 8.0.0.11: Added -Y.
Changed in version 8.4.0.1: Added -y/--make.
18.1.5 Language Run-Time Configuration
See also (part ("(lib scribblings/guide/guide.scrbl)" "module-runtime-config")) in (part ("(lib scribblings/guide/guide.scrbl)" "top")).
一个 module 可以有一个 configure-runtime submodule,当 module 是程序的主 module 时,在该 module 本身之前被 dynamic-require。通常,configure-runtime submodule 由 module 的语言(即 module 初始绑定中的 #%module-begin form)添加到 module 中。configure-runtime submodule 的主体通常设置 parameter,可能包括 current-interaction-info。
另外或此外,还有一个旧协议存在。当使用 #lang 实现 module 时,#lang 后的语言可以指定当使用该语言的 module 成为程序主 module 时所配置的操作。语言通过以下方式指定运行时配置:
将从其源读取的 module 附加一个 'module-language syntax property(参见 module 和 module-compiled-language-info);
让 'module-language syntax property 指示的函数识别 'configure-runtime key,并为其返回一个 vector 列表;每个 vector 必须具有 (vector mp name val) 的形式,其中 mp 是 module path,name 是 symbol,val 是任意值;以及
让每个函数以 ((dynamic-require mp name) val) 的形式被调用,以配置运行时环境,通常是通过设置诸如 current-print 之类的 parameter。
'configure-runtime 查询返回一个 vector 列表,而不是直接配置环境,以便在创建独立可执行文件时将指定的 module 与程序捆绑在一起;参见 (part ("(lib scribblings/raco/raco.scrbl)" "top")) 中的 (part ("(lib scribblings/raco/raco.scrbl)" "exe"))。
有关定义新的 #lang 语言,参见 syntax/module-reader。
18.1.6 Language Expand Configuration
lang module 可以有一个 configure-expand submodule 当另一个 module 被实现为 (module name lang ....) 时,该 submodule 在其展开之前被 dynamic-require。 子模块在 root namespace 中加载,与 reader module 相同。submodule 应提供 enter-parameterization 和 exit-parameterization 作为 procedure,每个接受零个参数并返回一个 parameterization:
对于 lang 的 enter-parameterization 在 module (module name lang ....) 的展开开始时被调用,该 parameterization 通过 call-with-parameterization 包装 module 展开。
对于 lang 的 exit-parameterization 在 (module name lang ....) 的展开触发了其他 module 的展开时被调用,通常是因为它们被正在展开的 module require。在这种情况下,调用 exit-parameterization 获取一个 parameterization,该 parameterization 被置于对新展开 module 的语言的 enter-parameterization 调用的周围。
current-parameterization procedure 同时作为 enter-parameterization 和 exit-parameterization 的默认值。
enter-parameterization 产生的 parameterization 通常设置影响展开期间错误报告的 parameter,如 error-syntax->string-handler。exit-parameterization 产生的 parameterization 通常应恢复 enter-parameterization 所做的更改,同时保留其他 parameter 值不变(如 current-load-relative-directory)。要从 enter-parameterization 的使用向嵌套的 exit-parameterization 使用通信,请使用私有的 parameter。
enter-parameterization 和 exit-parameterization procedure 预期基于当前 parameterization 构建,但通常不应修改当前 parameter,因为这种修改会超出返回的 parameterization 的使用范围。相反,使用 parameterize 创建包含更新后 parameter 值的新 parameterization。enter-parameterization 和 exit-parameterization 也不应操作当前 namespace,因为这会干扰 module 展开。
Added in version 8.8.0.6 of package base.