$ clj
Clojure 1.11.2
user=>
clojure.main/main
入口点接受各种参数和标志。
没有选项或参数,运行一个交互式的 Read-Eval-Print 循环
初始化选项
-i, --init path 加载文件或资源
-e, --eval string 在字符串中执行表达式; 打印非 nil 值
--report target 将未捕获的异常报告给 "file"(默认)、"stderr" 或 "none",覆盖系统属性 clojure.main.report(在 1.10.1 中添加)
主选项
-r, --repl 运行一个 repl
path 从文件或资源运行一个脚本
- 从标准输入运行一个脚本
-m, --main 用于执行的命名空间,用于查找 -main 函数
-h, -?, --help 打印此帮助消息并退出
操作
为通常可 set!-able 的 var 建立线程局部绑定
进入 user 命名空间
将 *command-line-args*
绑定到一个字符串序列,包含在任何主选项之后出现的命令行参数
按顺序运行所有初始化选项
如果请求,运行 repl 或脚本
初始化选项可以重复和自由混合,但必须出现在任何主选项之前。任何求值选项在运行 repl 之前出现,会抑制通常的 repl 问候消息:“Clojure ~(clojure-version)”。
路径可以是文件系统中的绝对路径或相对路径,也可以是相对于类路径的相对路径。类路径相关的路径以 @ 或 @/ 为前缀
启动 Clojure repl 的最简单方法是使用 clj 命令工具,该工具调用 clojure.main
$ clj
Clojure 1.11.2
user=>
REPL 提示符显示当前命名空间 (*ns*) 的名称,默认为 user。
在使用 REPL 时,可以使用几个特殊的 var
*1, *2, *3 - 保持最后三个被求值的表达式的结果
*e - 保存最后一个异常的结果。
clojure.repl 命名空间有一些有用的函数,用于检查可用函数的源代码和文档
要向脚本传递参数,在启动 clojure.main
时将它们作为进一步的参数传递
clj -M /path/to/myscript.clj arg1 arg2 arg3
这些参数将作为绑定到 var *command-line-args*
的字符串序列提供给您的程序
*command-line-args* => ("arg1" "arg2" "arg3")
从 Clojure 1.10 开始,Clojure 错误被归类为几个阶段中的一个
:read-source
- 在 REPL 或源文件中读取字符时抛出的错误。
:macro-syntax-check
- 在宏调用的语法中发现的语法错误,无论是来自 spec 还是来自抛出 IllegalArgumentException、IllegalStateException 或 ExceptionInfo 的宏。
:macroexpansion
- 在宏求值期间抛出的所有其他错误都归类为宏扩展错误。
:compile-syntax-check
- 在编译期间捕获的语法错误。
:compilation
- 在编译期间捕获的非语法错误。
:execution
- 在执行时抛出的任何错误。
:read-eval-result
- 在读取执行结果时抛出的任何错误(仅适用于读取结果的 REPL)。
:print-eval-result
- 在打印执行结果时抛出的任何错误。
在所有阶段(除 :execution
外)抛出的异常将附带 ex-data,其中包含以下一个或多个键
:clojure.error/phase
- 阶段指示器
:clojure.error/source
- 文件名(无路径)
:clojure.error/line
- 整数行号
:clojure.error/column
- 整数列号
:clojure.error/symbol
- 被扩展/编译/调用的符号
:clojure.error/class
- 导致异常的类符号
:clojure.error/cause
- 导致异常的消息
:clojure.error/spec
- spec 错误的 explain-data
clojure.main REPL 默认包含错误的分类和打印,但此过程的各个步骤也暴露出来,供其他 REPL 使用,特别是函数
Throwable->map - 将异常链转换为 Clojure 数据
ex-triage - 分析 Clojure 异常数据,从异常链的顶部和底部提取相关信息,放入一个映射中,描述仅用于格式化异常字符串的数据集
ex-str - 给定一组异常数据,生成一个阶段适当的消息
clojure.main REPL 将这些函数组合成一个管道,以生成打印的异常消息:(-> ex Throwable->map clojure.main/ex-triage clojure.main/ex-str)
。其他 REPL 可以根据需要使用此管道的一个或多个部分,在构建或定制其异常打印时。
直到 Clojure 1.10.0,clojure.main 在用作程序启动器(使用 -m、-e 或脚本)时,未捕获的异常会自动打印,以及完整的嵌套堆栈跟踪。在这种情况下,上面的错误分类和打印过程没有应用。
从 Clojure 1.10.1 开始,未捕获的异常现在将根据与 Clojure REPL 相同的错误分类和打印功能进行捕获和打印。完整的堆栈跟踪、ex-info 和其他信息将打印到由配置指定的目标。
三个可用的错误目标是
file
- 写入一个临时文件(默认,回退到 stderr
)
stderr
- 写入 stderr 流
none
- 不写入
这些错误目标可以作为 clojure.main 的选项指定,也可以作为 Java 系统属性指定(标志优先)。在调用 clojure.main(或使用 clj 工具)时,使用 --report <target>
。对于 Java 系统属性,使用 -Dclojure.main.report=<target>
。
其他程序可能希望利用此功能,它在 report-error 中可用,它接受一个 Throwable 和可选的 :target。
user.clj
Clojure 运行时将在运行时启动时查找并加载 user.clj
,如果它在类路径中找到。
因为 user.clj
文件是在 Clojure 运行时初始化时加载的,所以这通常发生在应用程序中的主命名空间执行之前。因此,user.clj
加载的任何命名空间或资源都会影响应用程序的启动时间。
tap 是一个共享的、全局可访问的系统,用于将一系列信息或诊断值分发到一组(可能是 effectful 的)处理程序函数。它可以用来代替更好的调试 prn
,或者用于日志记录等功能。
tap>
将值发送到一组 tap。可以使用 add-tap
添加 tap,并且将使用发送到 tap> 的任何值调用它们。tap 函数可能会(短暂地)阻塞(例如,对于流),并且永远不会阻碍对 tap> 的调用,但无限期阻塞可能会导致 tap 值被丢弃。如果没有注册任何 tap,tap> 会丢弃。使用 remove-tap
移除 tap。
Clojure 运行时现在能够在初始化时基于系统属性启动套接字服务器。此功能的一个预期用途是提供基于套接字的 REPL,但也具有许多其他潜在用途,例如在不更改代码的情况下为现有程序动态添加服务器功能。
对于每个类似于“clojure.server.<server-name>”的 JVM 系统属性,将启动一个套接字服务器。此属性的值是一个 edn 映射,它表示套接字服务器的配置,具有以下属性
server-daemon
- 默认值为 true,套接字服务器线程不阻止退出
address
- 主机或地址,默认为环回
port
- 正整数,必填
accept
- 在套接字接受时要调用的函数的命名空间符号,必填
args
- 要传递给 accept 的参数的顺序集合
bind-err
- 默认值为 true,将 *err*
绑定到套接字输出流
client-daemon
- 默认值为 true,套接字客户端线程不阻止退出
此外,还提供了一个 REPL 函数,它经过稍微定制,可与 clojure.core.server/repl 中的套接字服务器一起使用。
以下是启动带有 REPL 侦听器的套接字服务器的示例。这可以添加到任何现有的 Clojure 程序中,以允许它通过对端口 5555 的本地连接接受外部 REPL 客户端。
-Dclojure.server.repl="{:port 5555 :accept clojure.core.server/repl}"
使用 Clojure CLI,使用 -J
标志将选项传递给 JVM(注意,这也会除了套接字 REPL 之外启动一个本地 REPL)
clj -J-Dclojure.server.repl="{:port 5555 :accept clojure.core.server/repl}"
您可以用来远程连接到此 REPL 的示例客户端是 telnet(也可以使用 netcat
)
$ telnet 127.0.0.1 5555
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
user=> (println "hello")
hello
您可以通过使用特殊命令 :repl/quit
指示服务器关闭客户端 REPL 会话
user=> :repl/quit
Connection closed by foreign host.
另请参见
主入口点:clojure.main/main
可重用 REPL:clojure.main/repl
允许对习惯的 REPL 变量进行 set!:clojure.main/with-bindings
套接字服务器控制:clojure.core.server/start-server
clojure.core.server/stop-server
clojure.core.server/stop-servers
套接字 REPL:clojure.core.server/repl