Clojure

REPLとメインのエントリポイント

clojure.main名前空間

clojure.main名前空間は、ClojureプログラムとインタラクティブセッションをJavaのアプリケーションランチャーツールjava経由で起動できるようにする関数を提供します。

clojure.main --help

clojure.main/mainのエントリポイントは、さまざまな引数とフラグを受け付けます。

  • オプションや引数がない場合、インタラクティブなRead-Eval-Print Loopを実行します。

  • 初期化オプション

    • -i, --init パス ファイルまたはリソースをロードします

    • -e, --eval 文字列 文字列内の式を評価します。nil以外の値をプリントします

    • --report ターゲット キャッチされなかった例外を「ファイル」(デフォルト)、「stderr」、または「none」にレポートします。システムプロパティclojure.main.reportをオーバーライドします(1.10.1で追加)。

  • メインオプション

    • -r, --repl REPLを実行します

    • パス ファイルまたはリソースからスクリプトを実行します

    • - 標準入力からスクリプトを実行します

    • -m, --main 実行するための-main関数を見つける名前空間

    • -h, -?, --help このヘルプメッセージをプリントして終了します

  • 操作

    • 頻繁にset!される変数に対してスレッドローカルなバインディングを確立します

    • user名前空間に入ります

    • *command-line-args*をメインオプションの後に出現するコマンドライン引数を含む文字列のシーケンスにバインドします

    • すべての初期化オプションを順番に実行します

    • 要求された場合はREPLまたはスクリプトを実行します

初期化オプションは繰り返し、自由に混在させることができますが、メインオプションの前に出現する必要があります。REPLの実行前にevalオプションが出現すると、通常のREPLの挨拶メッセージ「Clojure ~(clojure-version)」が抑制されます。

パスは、ファイルシステム内で絶対パスまたは相対パスにすることができ、クラスパスに対して相対パスにすることもできます。クラスパス相対パスには、@または@/のプレフィックスが付いています。

REPLの起動

Clojureのreplを起動する最も簡単な方法は、clojure.mainを呼び出すcljコマンドツールを使用することです。

$ clj
Clojure 1.11.2
user=>

REPLプロンプトには、現在の名前空間(*ns*)の名前が表示されます。デフォルトはuserです。

REPLを使用すると、いくつかの特別な変数が利用できます。

  • *1, *2, *3 - 評価された最後の3つの式の結果を保持します

  • *e - 最後の例外の結果を保持します。

clojure.repl名前空間には、利用可能な関数のソースとドキュメントを検査するための多くの便利な関数があります。

  • doc - 名前が指定された変数のドキュメント文字列をプリントします

  • find-doc - ドキュメントまたは名前がパターンに一致する任意の変数のドキュメント文字列をプリントします

  • apropos - 正規表現に一致する定義のシーケンスを返します

  • source - シンボルのソースをプリントします

  • pst - 指定された例外またはデフォルトで*eのprint stack traceをプリントします

スクリプトの起動

Clojureコードでいっぱいのファイルをスクリプトとして実行するには、スクリプトへのパスを引数としてclojure.mainに渡します。

clj -M /path/to/myscript.clj

スクリプトへの引数の渡し方

スクリプトに引数を渡すには、clojure.mainを起動するときに追加の引数として渡します。

clj -M /path/to/myscript.clj arg1 arg2 arg3

引数は、変数*command-line-args*にバインドされた文字列のシーケンスとしてプログラムに提供されます。

*command-line-args* => ("arg1" "arg2" "arg3")

エラー出力

REPLでの場合

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)中にスローされた例外には、次のキーの1つ以上を含む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エラーの説明データ

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は、例外の印刷を構築またはカスタマイズするときに、必要に応じてこのパイプラインの1つまたは複数の部分を使用できます。

ランチャーとしての場合

Clojure 1.10.0まで、プログラムランチャーとして使用した場合(-m、-e、またはスクリプトを使用)、キャッチされなかった例外は、完全なネストされたスタックトレースとともに自動的に印刷されました。この場合、上記のエラートリアージと印刷プロセスは適用されませんでした。

Clojure 1.10.1以降、キャッチされなかった例外は、Clojure REPLと同じエラートリアージおよび印刷機能に従ってキャッチされ、印刷されるようになりました。完全なスタックトレース、ex-info、およびその他の情報は、構成で指定されたターゲットに印刷されます。

利用可能な3つのエラーターゲットは次のとおりです。

  • file - 一時ファイルに書き込みます(デフォルト、stderrにフォールバックします)

  • stderr - stderrストリームに書き込みます

  • none - 書き込みません

これらのエラーターゲットは、clojure.mainのオプションとして、またはJavaシステムプロパティとして指定できます(フラグが優先されます)。clojure.mainを呼び出す(またはcljツールを使用する)場合は、--report <target>を使用します。Javaシステムプロパティの場合は、-Dclojure.main.report=<target>を使用します。

他のプログラムは、この機能を利用したい場合があります。これはreport-errorで利用できます。これは、Throwableとオプションで:targetを受け取ります。

user名前空間

デフォルトでは、Clojure REPLはuser名前空間で開始され、この名前空間は通常、探索的な作業に使用されます。

Clojure REPLは、次の名前空間を自動的にロードし、次の関数を参照します

異なる名前空間(in-nsnsを使用)に切り替えた場合、これらの関数は明示的に参照しない限り利用できません。

user.clj のロード

Clojureランタイムは、起動時にクラスパス上に user.clj が見つかると、それをロードします。これは開発時の機能を提供する目的で設計されており、一般的に本番環境での使用は推奨されていません。

user.clj ファイルはClojureランタイムによって初期化時にロードされるため、通常、アプリケーションのメイン名前空間が実行される前に発生します。したがって、user.clj によってロードされる名前空間やリソースは、アプリケーションの起動時間に影響を与えます。

tap

tapは、一連の情報または診断値を、(おそらく効果的な)ハンドラー関数のセットに配信するための、共有されたグローバルにアクセス可能なシステムです。より良いデバッグ用 prn として、またはロギングなどの機能に使用できます。

tap> は、値をタップのセットに送信します。タップは add-tap で追加でき、tap> に送信されたすべての値で呼び出されます。タップ関数は(一時的に)ブロックする可能性があり(例:ストリームの場合)、tap> の呼び出しを妨げることはありませんが、無期限にブロックするとタップの値が破棄される可能性があります。タップが登録されていない場合、tap> は破棄します。タップは remove-tap で削除します。

ソケットサーバーの起動

Clojureランタイムには、システムプロパティに基づいて初期化時にソケットサーバーを起動する機能が追加されました。この機能の想定される使用例の一つは、ソケットベースのREPLを提供することですが、コードを変更せずに既存のプログラムにサーバー機能を動的に追加するための多くの潜在的な用途もあります。

ソケットサーバーは、"clojure.server.<server-name>" のような各JVMシステムプロパティに対して起動されます。このプロパティの値は、ソケットサーバーの構成を表すednマップで、次のプロパティを持ちます。

  • server-daemon - デフォルトはtrueで、ソケットサーバーのスレッドは終了をブロックしません

  • address - ホストまたはアドレス、デフォルトはループバック

  • port - 正の整数、必須

  • accept - ソケット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

ソケットREPL:clojure.core.server/repl