-sスイッチを使って実行する
コマンドの形式と動作-
guileコマンドの-sスイッチを利用することによって,REPLに入ることなくプログラムが実行できます.コマンドの実行形式は次の通りです.
$ guile -s file ↵
ここで,fileはプログラムファイルを表しています.このコマンドを実行すると,file内のプログラムがコンパイルされて実行されます. -
具体例として,以下のプログラムを greetings.scm というファイルに保存したとします.
;; greetings.scm (display "Hello, Scheme!!!\n") (display "Hello, Guile!!!\n")
このプログラムを実行してみます.$ guile -s greetings.scm ↵ ...... コンパイルメッセージ ...... Hello, Scheme!!! Hello, Guile!!!
-
(参考)REPLによって実行したときと同様に,コンパイル後のバイトコードがキャッシュディレクトリに保存されます.そのバイトコードが古くならない限り(つまり,ソースコードが変更されない限り),再コンパイルは行われずにバイトコードが実行されます.
$ guile -s greetings.scm ↵ Hello, Scheme!!! Hello, Guile!!!
-
(参考)プログラムファイル名がハイフン(-)で始まるのでない限り,
'-s'を省略できます.
$ guile greetings.scm ↵ Hello, Scheme!!! Hello, Guile!!!
-
上で示したコマンド形式にコマンドライン引数を指定することもできます.
$ guile -s file arg ... ↵
ここで,argはプログラムへの入力データとして利用される任意の記号列を表します.記号列は幾つでも指定できて,各記号列は空白によって区切ります.これを実行すると,file内のプログラムを実行する前に,'("file" "arg" ... )といった文字列からなるリストが構成され,file内のプログラムへ入力データとして渡されます.このリストはcommand-list手続きを使って取得できます. - (注意)プログラムに渡されるコマンドライン引数のリストの先頭は,プログラムのファイル名です.2番目以降の要素が実際の入力データになります.
-
具体例として,以下のプログラムをarglist.scmというファイルに保存したとします.
;; arglist.scm (write (command-line)) (newline)
このプログラムは,コマンドライン引数から構成された'("arglist.scm" "AAA" "BBB" "CCC")というリストをcommand-line手続きを使って取得して,そのリストを表示(write)して改行(newline)します.$ guile -s arglist.scm AAA BBB CCC ↵ ...... コンパイルメッセージ ...... ("arglist.scm" "AAA" "BBB" "CCC")
-
簡単な具体例をもう一つ示しましょう.以下のプログラムを改めてgreetings.scmに保存したとします.
;; greetings.scm (define name (cadr (command-line))) (display (string-append "*** Hello," name "!!! ***")) (newline)
このプログラムは,まず,コマンドライン引数として与えられたリストから名前(以下の実行例では"Alice")を取り出して,その名前を変数nameに束縛します.次に,その文字列の前後に "*** Hello," と "!!! ***" といった文字列を連結(string-append)して,連結後の文字列を表示(display)して改行(newline)します.$ guile -s greetings.scm Alice ↵ ...... コンパイルメッセージ ...... *** Hello,Alice!!! ***
-eスイッチを使ってエントリーポイントを指定する
コマンドの形式と動作-
-sスイッチと一緒に-eスイッチを利用することによって,プログラム内のエントリーポイント(実行を開始する手続き)を指定することができます.コマンドの形式は次の通りです.
$ guile -e proc -s file ↵ または $ guile -e proc -s file arg ... ↵
ここで,procはプログラム内の手続き名を表します.2番目の形式は,コマンドライン引数(arg ...)を指定する場合を示しています. -
上記のコマンドを実行したとき,Guileはプログラムを次のように処理します.
- まず,プログラムをコンパイルします(REPLのときと同様に,バイトコードが最新のときには再コンパイルはしません).
- 次に,1番目のコマンドを実行したとき(つまり,コマンドライン引数を指定しなかったとき),
'("file")といったリストを構成し,2番目のコマンドを実行したとき(つまり,コマンドライン引数を指定したとき)には,'("file" "arg" ... )といったリストを構成します.
- 次に,プログラム内のすべての定義と式を先頭から順に評価します.
- そのあとで,上で構成したリストに対してprocを適用します( つまり,上記のリストを実引数としてprocを実行します).
-
具体例として,次のプログラムをgreetings.scmに保存したとします.
;; greetings.scm (define (hello-scheme args) (display "*** Hello, Scheme!!! ***") (newline)) (define (hello-guile args) (display "*** Hello, Guile!!! ***") (newline))
それぞれの手続きをエントリーポイントとして実行してみます.$ guile -e hello-scheme -s greetings.scm ↵ ...... コンパイルメッセージ ...... *** Hello, Scheme!!! *** $ guile -e hello-guile -s greetings.scm ↵ *** Hello, Guile!!! ***
1番目のコマンドはhello-scheme手続きを実行し,2番目はhello-guile手続きを実行しています.なお,1番目のときにコンパイルが済んでいるので,2番目のときにはコンパイルされません. -
コマンドライン引数を利用する具体例として,次のプログラムを改めてgreetings.scmに保存したとします.
;; greetings.scm (define (hello-everybody args) (write args) (newline) (for-each hello-somebody (cdr args))) (define (hello-somebody arg) (display (string-append "*** Hello," arg "!!! ***")) (newline))
hello-everybody手続きをエントリーポイントとしてプログラムを実行してみます.$ guile -e hello-everybody -s greetings.scm Alice Bob Carol ↵ ...... コンパイルメッセージ ...... ("greetings.scm" "Alice" "Bob" "Carol") *** Hello,Alice!!! *** *** Hello,Bob!!! *** *** Hello,Carol!!! ***
hello-everybodyは,ファイル名を含めたコマンドライン引数からなるリスト'("greetings.scm" "Alice" "Bob" "Carol")を実引数として受け取って,そのリストを表示(write)して改行(newline)したあと,先頭要素(ファイル名)を除く残りの各文字列("Alice","Bob","Carol")に対してhello-somebodyを適用しています.hello-somebodyは,引数として受け取った文字列の前後に"*** Hello,"と"!!! ***"を連結(string-append)して,連結後の文字列を表示(display)して改行(newline)しています. -
(参考)エントリーポイントのprocへ実引数として渡されたリストは,プログラム全体への入力データとして渡されてもいるため,command-line手続きを使って取得することもできます.つまり,エントリーポイントを指定したとき,コマンドライン引数は2つの方法で取得できることになります.例えば,次のプログラムをarglist.scmに保存したとします.
;; arglist.scm (define (get-arguments args) (display "arg:") (write args) (newline) (display "cmd:") (write (command-line)) (newline))
get-arguments手続きをエントリーポイントとしてプログラムを実行してみます.$ guile -e get-arguments -s arglist.scm AAA BBB CCC ↵ ...... コンパイルメッセージ ...... arg:("arglist.scm" "AAA" "BBB" "CCC") cmd:("arglist.scm" "AAA" "BBB" "CCC")
get-arguments手続きは,コマンドライン引数からなるリスト'("greetings.scm" "AAA" "BBB" "CCC")を実引数(args)として受け取って,そのリストを表示して改行しています.さらに,その同じリストをcommand-line手続きによって取得して表示して改行しています.
-
コマンドライン引数(arg ...)を何も指定しないときでも
'("file")といったリスト(ファイル名だけからなるリスト)がエントリーポイントの手続きに実引数として渡されます.従って,エントリーポイントの手続きは必ず仮引数を用意しなければなりません.そうしないとエラーが発生します.
-
具体例として,次のプログラムをnoparam.scmに保存したとします.
;; noparam.scm (define (hello-scheme) (display "*** Hello, Scheme!!! ***") (newline))
hello-scheme手続きをエントリーポイントに指定してプログラムを実行してみます.$ guile -e hello-scheme -s noparam.scm ...... コンパイルメッセージ ...... Backtrace: ...... バックトレースに関するメッセージ ...... /home/user/tmp/noparam.scm:2:0: In procedure hello-scheme: Wrong number of arguments to #<procedure hello-scheme ()>
赤字がエラーメッセージで,「引数の個数が間違えている」と怒っています. つまり,hello-schemeにはファイル名だけからなるリストを実引数として渡さなければならなかったのですが,それが出来なかったのでエラーが発生したのです.
-
エントリーポイントを指定したときのプログラムの動作を,用心のため,再確認しておきましょう.前に述べたように,エントリーポイントを指定して
$ guile -e proc -s file ↵というコマンドを実行たとき,Guileはプログラムを次のように処理します.
または
$ guile -e proc -s file arg ... ↵- まず,プログラムをコンパイルします(REPLのときと同様に,バイトコードが最新のときには再コンパイルはしません).
- 次に,1番目のコマンドを実行したとき(つまり,コマンドライン引数を指定しなかったとき),
'("file")といったリストを構成し,2番目のコマンドを実行したとき(つまり,コマンドライン引数を指定したとき)には,'("file" "arg" ... )といったリストを構成します.
- 次に,プログラム内のすべての定義と式を先頭から順に評価します.
- そのあとで,上で構成したリストに対してprocを適用します( つまり,上記のリストを実引数としてprocを実行します).
-
注意すべき要点は,
- プログラム内のすべての定義と式が評価されたあとにprocが最後に実行される
-
簡単な具体例として,次のプログラムをmain手続きをエントリーポイントとして実行してみます.ファイル名はentry-point.scmとします.
;; entry-point.scm (define (main args) (display x) (newline)) (define x "I am X!!!")
main手続きから実行が開始されると素朴に考えたとき,mainの本体を実行した時点で変数xは未束縛なのでエラーが出るように思います.でも,その考えは間違いです.これは問題なく動きます.なぜならxの定義が評価されたあとにmain手続きが実行されるからです.$ guile -e main -s entry-point.scm ↵ ...... コンパイルメッセージ ...... I am X!!!
-
さらに,上のプログラムを次のように変更して実行してみると,定義や式の評価を先頭から順に行ったあとにエントリーポイントが実行されることがよく分かります.
;; entry-point.scm (define (main args) (display x) (newline)) (define x "I am X!!!") (display "*** THE LAST LINE OF THIS PROGRAM ***") (newline)
以下の実行結果は,上記の最終行にあるdisplay手続きとnewline手続きを実行したあとにエントリーポイントのmain手続きが呼び出されていることを示しています.$ guile -e main -s entry-point.scm ↵ ...... コンパイルメッセージ ...... *** THE LAST LINE OF THIS PROGRAM *** I am X!!!
-
(参考)エントリーポイント(proc)を指定して実行することは,procの呼び出しを最後に明記して,エントリーポイントを指定せずに実行することと同じです.例えば,上で示したプログラムは,次のように変更(mainの呼び出しを追加)してエントリーポイントを指定せずに実行することと同じです.
;; entry-point.scm (define (main args) (display x) (newline)) (define x "I am X!!!") (display "*** THE LAST LINE OF THIS PROGRAM ***") (newline) (main (command-line)) (注) mainの呼び出しを追加
$ guile -s entry-point.scm ↵ (注) エントリーポイントを指定しない ...... コンパイルメッセージ ...... *** THE LAST LINE OF THIS PROGRAM *** I am X!!!
(おしまい)