ファイルのインタプリタ実行
.lisp ファイルのパスを渡すと、rontolisp はコンパイル成果物を生成せずに
そのまま解釈実行します。ファイルのトップレベルフォームはツリーウォーク
インタプリタによって順番に読み込まれ評価され、1 つの環境を共有します。
そのため、上の方で定義された関数や変数は、それより下のすべてから利用できます。
rontolisp program.lisp
REPL と異なり、スクリプトは各フォームの値をエコーしません。出力は、プログラムが
print や format などで明示的に書き出したものだけです。プロセスは、ファイルが
最後まで実行されるとステータス 0 で終了し、フォームがエラーを通知した場合は
非ゼロで終了します。
例(program.lisp):
25
144
これは、後で JVM や WASM コンパイラに渡すのと同じソースです。まずインタプリタで 実行することは、コンパイル前にプログラムの動作を確認する最も速い方法です。
インタプリタ実行の速度
インタプリタはターンアラウンドのために作られており、スループットのためでは ありません。即座に起動し、コンパイラが固定されているのとまったく同じセマンティクスで 実行しますが、タイトなループは反復のたびに解釈コストを支払い、時間が経っても 速くなることはありません。ループ中心のコードでは、同じファイルをコンパイルした 場合と比べて 20 倍〜200 倍 のコストになります。最初の 1000 万個の整数の合計は、 インタプリタでは数秒かかりますが、コンパイル済みのクラスや WASM モジュールなら 1 秒未満です。
ファイルを読む、HTTP API を呼ぶ、リクエストを捌くといったスクリプトでは、 時間は I/O に費やされるためこの倍率は見えず、インタプリタ実行が適切な デフォルトです。プログラムが CPU バウンド(数値ループ、パース、暗号処理)の 場合は、コンパイルして成果物を実行してください。
rontolisp program.lisp -o program.jar
java -jar program.jar
コンパイル済み出力が高速なパスです。JVM でも WASM でも同様です。 JVM バイトコードへのコンパイル と WASM へのコンパイル を参照してください。
再帰の深さ
インタプリタはホストのスタック上で再帰します。呼び出し先が戻った後にまだ仕事が残っている
Lisp 呼び出しはそれぞれインタプリタのフレームを保持するため、深い再帰を行うプログラムは
スタックを使い切ることがあります。末尾位置の呼び出し(関数が最後に行う呼び出しで、関数値や
apply を通した呼び出し、互いに呼び合う関数どうしの呼び出し、関数を抜ける return-from/return
の値(ループ本体からのものを含む)を含みます)はフレームを保持
しないため、末尾再帰として書いたループはどんな深さでも実行できます。rontolisp はプログラムを
専用のスレッド上で、16 MiB のスタックを与えて実行します。そのため到達できる深さはプラットフォームや
起動方法によらず同じ値になります(java -jar の -Xss は、プログラムが
もう動いていないスレッドの大きさを決めるだけです)。より大きくしたい場合は
--stack に MiB 単位で指定します。
rontolisp --stack 64 deep.lisp
スタックより深いプログラムは error: stack overflow (--stack <MiB> raises the limit) を
出力し、終了ステータス 1 で停止します。対処はこのオプションを使うか、再帰を反復による形に
書き換えるかのどちらかです。REPL では同じオーバーフローが報告され、それまでの定義を保ったまま
セッションが続きます。
コマンドラインで与えるプログラム
-e(長い綴りは --eval)は、プログラムをファイルではなく引数そのものから
受け取ります。実行のされ方はファイルとまったく同じで、値はエコーされず、
プログラムが出力したものだけが表示されます。
rontolisp -e "(print (+ 1 2))"
3
このオプションは繰り返し指定でき、指定された分がまとめて 1 つのプログラムとなり 順に評価されます。1 つのファイルに各フォームを続けて書いた場合と同じです。
rontolisp -e "(defun square (x) (* x x))" -e "(print (square 5))"
25
ファイルが受け付けるものはすべて併用でき、コンパイラも同様です
(rontolisp -e "(print (+ 1 2))" -o Prog.class)。ただし入力ファイルとの併用は
できません。プログラムはどちらか一方の方法で与えてください。ソースファイルが
存在しないため、相対パスの (load "...") はカレントディレクトリを基準に解決されます。