$ clj
Clojure 1.10.0
user=>
clojure.main
の名前空間はJavaのアプリケーションランチャーツール java
からClojureプログラムやインタラクティブなセッションを起動するための関数を提供している。
clojure.main/main
のエントリーポイントは多様な引数とフラグを受けとる:
オプションと引数の指定がない場合、インタラクティブな REPL (Read-Eval-Print Loop) を実行する
initオプション:
-i, --init パス ファイル、もしくはリソースをロードする
-e, --eval 文字列 文字列中の式を評価する; 非nilな値をプリントする
--report target Report uncaught exception to "file" (default), "stderr", or "none", overrides System property clojure.main.report (added in 1.10.1)
mainオプション:
-r, --repl replを実行する
path ファイル、もしくはリソースからスクリプトを実行する
- 標準入力からスクリプトを実行する
-m, --main 実行対象の-main関数を見つけるための名前空間
-h, -?, --help このメッセージをプリントして終了する
操作:
一般的に利用されるset!操作が可能なvarに対してスレッドローカルな束縛を行う
user名前空間に切り替える
Binds *command-line-args*
to a seq of strings containing command
line args that appear after any main option
全てのinitオプションを順に実行する
repl、もしくは指定があればスクリプトを実行する
initオプションは繰り返しても良いし任意に組み合せることができるが、mainオプションよりも前に指定する必要がある。replの実行前にevalのオプションが指定されている場合、通常のreplのグリーティングメッセージが表示されなくなる: "Clojure ~(clojure-version)"
パスは絶対パス、もしくはファイルシステムの相対パス、クラスパスに対する相対パスを指定できる。クラスパスに対する相対パスは @ もしくは @/ でプリフィックスされる。
The simplest way to launch a Clojure repl is to use the clj command tool, which invokes clojure.main:
$ clj
Clojure 1.10.0
user=>
REPLプロンプトは現在の名前空間の名前 (*ns*) を表示し、デフォルトは user である。
REPLを利用している際には、特別なvarをいくつか利用できる:
*1, *2, *3 - 評価済みの最後の3つの式の結果を保持する
*e - 最後に発生した例外の結果を保持する
clojure.repl 名前空間には、利用可能な関数のソースやドキュメントの閲覧に有用な関数がいくつもある:
Clojureコードが書かれたファイルをスクリプトとして実行するには、スクリプトのパスを clojure.main
の引数として渡す:
clj /path/to/myscript.clj
スクリプトの引数は clojure.main
を起動する際の追加の引数として渡す:
clj /path/to/myscript.clj arg1 arg2 arg3
これらの引数はプログラム内のvar *command-line-args*
に束縛された文字列のseqとしてプログラムに提供される:
*command-line-args* => ("arg1" "arg2" "arg3")
As of Clojure 1.10, Clojure errors categorized into one of several phases:
:read-source
- an error thrown while reading characters at the REPL or
from a source file.
:macro-syntax-check
- a syntax error found in the syntax of a macro call,
either from spec or from a macro throwing IllegalArgumentException,
IllegalStateException, or ExceptionInfo.
:macroexpansion
- all other errors thrown during macro evaluation are
categorized as macroexpansion errors.
:compile-syntax-check
- a syntax error caught during compilation.
:compilation
- non-syntax errors caught during compilation.
:execution
- any errors thrown at execution time.
:read-eval-result
- any error thrown while reading the result of execution
(only applicable for REPLs that read the result).
:print-eval-result
- any error thrown while printing the result of
execution.
Exceptions thrown during all phases (exception :execution
) will have
ex-data attached with one or more the following keys:
:clojure.error/phase
- phase indicator
:clojure.error/source
- file name (no path)
:clojure.error/line
- integer line number
:clojure.error/column
- integer column number
:clojure.error/symbol
- symbol being expanded/compiled/invoked
:clojure.error/class
- cause exception class symbol
:clojure.error/cause
- cause exception message
:clojure.error/spec
- explain-data for a spec error
The clojure.main REPL includes the categorization and printing of errors by default, but the individual steps of this process are exposed as well for other REPLs to use, specifically the functions:
converts an Exception chain into Clojure data
analyzes Clojure exception data to pull relevant information from the top and bottom of the exception chain into a map describing just the set of data needed to format an exception string
produces a phase-appropriate message given a set of exception data
The clojure.main REPL combines these functions in a pipeline to produce the
printed exception message: (-> ex Throwable->map
clojure.main/ex-triage clojure.main/ex-str)
. Other REPLs can use one or
more pieces of this pipeline as necessary when building or customizing their
exception printing.
Up to Clojure 1.10.0, clojure.main when used as a program launcher (with -m, -e, or with a script), uncaught exceptions would be automatically printed along with the full nested stack trace. In this case, the error triage and printing process above was not applied.
As of Clojure 1.10.1, uncaught exceptions will now be caught and printed according to the same error triage and printing functionality as the Clojure REPL. The full stack trace, ex-info, and other information will be printed to a target specified by the configuration.
The three available error targets are:
file
- write to a temp file (default, falls back to stderr
)
stderr
- write to stderr stream
none
- don’t write
These error targets can be specified either as options to clojure.main, or
as Java system properties (flags take precedence). When invoking
clojure.main (or using the clj tool), use --report <target>
. For Java
system property, use -Dclojure.main.report=<target>
.
Other programs may wish to take advantage of this functionality, and it is available in report-error, which takes a Throwable and optionally the :target.
tap is a shared, globally accessible system for distributing a series of
informational or diagnostic values to a set of (presumably effectful)
handler functions. It can be used as a better debug prn
, or for facilities
like logging etc.
tap>
sends a value to the set of taps. Taps can be added with
add-tap
and will be called with any value sent to tap>. The tap function may
(briefly) block (e.g. for streams) and will never impede calls to tap>, but
blocking indefinitely may cause tap values to be dropped. If no taps are
registered, tap> discards. Remove taps with
remove-tap
.
現在のClojureランタイムではシステムプロパティを基に、初期化時にソケットサーバーを起動することが可能となっている。想定される活用方法の一つはソケットベースのREPLだが、他にも既存のプログラムのコードの変更を行わずに動的にサーバー機能を追加する様々なことに利用可能なポテンシャルがある。
"clojure.server.<server-name>" のようなJVMシステムプロパティ全てに対してソケットサーバーが起動される。このプロパティの値には、ソケットサーバーの設定を表現する、下記のプロパティを持つednのマップを指定する:
server-daemon
- デフォルトでtrue、ソケットサーバーのスレッドがexitをブロックしない
address
- ホストもしくはアドレス、デフォルトはループバック
port
- 正の整数、必須
accept
- ソケットの受理時に呼び出される関数の名前空間付きのシンボル、必須
args
- acceptに渡す引数のシーケンシャルなコレクション
bind-err
- デフォルトtrue、 *err*
をソケットの出力ストリームに束縛する
client-daemon
- デフォルトでtrue、ソケットのクライアントのスレッドがexitをブロックしない
加えて、ソケットサーバーでの利用のために少々カスタマイズされているrepl関数が clojure.core.server/repl にある。
以下はソケットサーバーをreplリスナーとともに起動する例だ。これを任意のClojureプログラムに追加することで、外部からポート5555のローカルコネクションを経由したREPLクライアントを受理することが可能になる。
-Dclojure.server.repl="{:port 5555 :accept clojure.core.server/repl}"
このソケットreplには、例えばtelnetをクライアントとして接続することができる:
$ 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.
以下も参照:
Mainエントリーポイント:
clojure.main/main
再利用可能なREPL:
clojure.main/repl
Error handling:
clojure.main/ex-triage
clojure.main/ex-str
一般的なREPL varへの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