write,display,newline,simple-format(format)
procedure:
(write obj [port])
obj |
任意のオブジェクト |
port |
出力ポート.省略時はカレント出力ポートに出力する. |
返り値 |
unspecifed |
注意
上記の角括弧 [ ... ] は省略可能であることを示しています.
手続き呼び出しの構文要素ではありません.
この手続きは,obj の外部表現を port に出力します.port が省略されたときにはカレント出力ポートに出力します.
obj の外部表現は,read 手続きが読み取り可能な形式になります.
例えば,文字列はダブルクォートで囲まれた形式で出力され,
文字列内のエスケープ文字はそのまま出力されます(エスケープ文字は機能しません).
また,文字は #\ が付いた形式で出力されます.以下に,簡単な実行例を示します.
guile> (write #\a) (newline)
#\a
guile> (write "abc\tABC\n") (newline)
"abc\tABC\n"
guile> (write 'symbol) (newline)
symbol
guile> (write 123.456) (newline)
123.456
guile> (write '(a "a" #\a)) (newline)
(a "a" #\a)
procedure:
(display obj [port])
obj |
任意のオブジェクト |
port |
出力ポート.省略時はカレント出力ポートに出力する. |
返り値 |
unspecified |
注意
上記の角括弧 [ ... ] は省略可能であることを示しています.
手続き呼び出しの構文要素ではありません.
この手続きは,obj の表現を port に出力します.port が省略されたときにはカレント出力ポートに出力します.
obj の表現は,人間が自然に読める形式で出力されます.
例えば,文字列はダブルクォートなしで出力され,
文字列内のエスケープ文字は機能を発揮します.
また,文字は #\ のない形式(つまり,文字だけ)が出力されます.
以下に,簡単な実行例を示します.
guile> (display #\a) (newline)
a
guile> (display "abc\tABC\n") (newline)
abc ABC
guile> (display 'symbol) (newline)
symbol
guile> (display 123.456) (newline)
123.456
guile> (display '(a "a" #\a)) (newline)
(a a a)
上の2番目の文字列("abc\tABC\n")を出力する例では,タブ文字(\t)と改行文字(\n)が,出力の際に機能を発揮しています.abc と ABC が離れているのはタブ文字(\t)が機能したためです.また,出力結果の直後が空行になっているのは改行文字(\n)が機能して,さらに newline を実行したためです.さらに,最後の結果を見ると,シンボルの 'a と文字列の "a" と文字の #\a の出力結果は見分けが付きません.
procedure:
(newline [port])
port |
出力ポート.省略時はカレント出力ポートに出力する. |
返り値 |
unspecified |
注意
上記の角括弧 [ ... ] は省略可能であることを示しています.
手続き呼び出しの構文要素ではありません.
この手続きは,改行文字を port に出力します.port が省略されたときにはカレント出力ポートに出力します.
procedure:
(simple-format port fmt obj*)
(format port fmt obj*)
port |
出力ポート または ブール値 |
fmt |
文字列(書式指定) |
obj |
任意のオブジェクト |
返り値 |
ブール値または文字列 |
備考
format 手続きについて,下記の補足を参照して下さい.
これらの手続きは,オブジェクトの列 obj* を書式指定 fmt に沿って port に出力します.port に #t を指定した場合,カレント出力ポートに出力します.一方,#f を指定した場合,
書式指定に沿った出力を文字列として返します.出力を行った場合,出力が成功したら #t を返します.出力に失敗したら #f を返すだろうと推測されますが,たいていエラーが発生します.これまでのところ #f が返ってくるのを経験したことはありません.
書式指定の文字列は,\n や \t などのような文字列データとしてのエスケープ文字に加えて,obj を表示するための書式指定用のエスケープ(下表)を含むことができます.
エスケープ |
意味 |
~A ~a |
対応する obj を display 手続きと同じ形式で表示します.
|
~S ~s |
対応する obj を write 手続きと同じ形式で表示します.
|
~% |
改行を表示します(文字列エスケープの \n と同じです).
|
~~ |
ティルダ(~)を表示します.
|
書式指定文字列の中の ~A と ~S の個数と obj の個数は一致していなければいけません.そうでないとエラーが発生します.
具体例
以下では,数値,文字,文字列,シンボルに関して ~A と ~S の違いを示しています.
文字と文字列以外には出力形式に違いはないように思います.
guile> (simple-format #t "~A ~S\n" 123.45 123.45)
123.45 123.45
guile> (simple-format #t "~A ~S\n" #\a #\a)
a #\a
guile> (simple-format #t "~a ~s\n" "Guile" "Guile")
Guile "Guile"
guile> (simple-format #t "~a ~s\n" 'Guile 'Guile)
Guile Guile
以下では,port に #f を指定した場合の結果を示します.
#f を指定した場合,書式指定に沿った出力が文字列として返ってきます.
guile> (simple-format #f "~A ~S\n" 123.45 123.45)
$1 = "123.45 123.45\n"
guile> (simple-format #f "~A ~S\n" #\a #\a)
$2 = "a #\\a\n"
guile> (simple-format #f "~a ~s\n" "Guile" "Guile")
$3 = "Guile \"Guile\"\n"
guile> (simple-format #f "~a ~s\n" 'Guile 'Guile)
$4 = "Guile Guile\n"
なお,format 手続きでも同じことができます.
補足
Guileの起動時に実行される boot-9.scm の中で format は simple-format に束縛されます.ところが,
システム起動直後から (ice-9 format) モジュールで定義されている高機能版の
format手続き
が利用できます.この点を確認するため,以下では,REPLの起動直後に,
浮動小数点数の表示を simple-format と format で試してみています.simple-format はその機能がないので失敗しています.
$ guile
GNU Guile 3.0.5
...... 起動メッセージ ......
guile> (simple-format #t "~f\n" 123.45)
;;; <stdin>:1:0: warning: "~f\\n": unsupported format option ~f, use (ice-9 format) instead
In procedure simple-format: FORMAT: Unsupported format option ~f - use (ice-9 format) instead
guile> (format #t "~f\n" 123.45)
123.45
$1 = #t
つまり,Guileを起動する際のどこかのタイミングで format を再束縛しているものと思われます.(ice-9 format) モジュールの最後の行に
(module-set! the-root-module 'format format)
という式があって,これが関係しているのかも知れません.
simple-format は,boot-9.scm の中で(formatと名前を変えて)使われています.
これから考えて,おそらく起動時のメッセージ表示のために作ったものだろうと推測します.simple-format の format に対する利点は,たぶん,速いことだけです.
補足
(ice-9 format) モジュールの format 手続きについてさらに補足します.上で示したように REPL では高機能版の format 手続きが使えるようです.でも,スクリプトでは使えたり使えなかったりしています.使用の可否が安定していないのですが,その理由は不明です.高機能版の format を使うときには,やはり (ice-9 format) モジュールをロードしたほうがよいでしょう.
end-of-file オブジェクト
このあとに示す read 手続きなどの入力用の手続きは,
ファイルの終端(end of file)に到達したら end-of-file オブジェクト を返します.入力用手続きの返り値が end-of-file オブジェクトか否かを判定するためには次の手続きを使用します.
procedure:
(eof-object? obj)
この手続きは,obj が end-of-file オブジェクトのとき #t を返し,
そうでないとき #f を返します.
read
procedure:
(read [port])
port |
入力ポート.省略時はカレント入力ポートから入力する. |
返り値 |
データ(datum) |
注意
上記の角括弧 [ ... ] は省略可能であることを示しています.
手続き呼び出しの構文要素ではありません.
Guileデータの外部表現を port から入力して,
それが表現するデータそのものを返します.
port が省略されたときには,カレント入力ポート(current input port)から入力します.
例えば,文字データの外部表現 #\\$c$ を入力したときには文字データを返し,
文字列データの外部表現 " ... " を入力したときには文字列データを返し,
リストデータの外部表現 ( ... ) を入力したときにはリストデータを返します.
その他にも,Guileが扱うデータで外部表現を持つものはすべて入力できるはずです.
外部表現を入力したあと,入力した外部表現の直後までファイルポインタを移動します.
ただし,入力時点でファイルの終端に到達していたときには enf of file オブジェクトを返します.
具体例
以下のプログラムは,コマンドライン引数に指定されたファイル(filename)からGuileデータの外部表現を入力して,そのデータを型とともに表示します.(srfi srfi-1) モジュールは,SRFI-1[Searching] で定義されている any 手続きを使うためにロードしています.
;; show-type.scm
(use-modules (srfi srfi-1))
(define *type-list*
(list number? char? string? symbol? keyword? list? pair? vector?))
(define (check-type datum)
(lambda (type?) (and (type? datum) (procedure-name type?))))
(let ((filename (cadr (command-line))))
(call-with-input-file filename
(lambda (port)
(let loop ((datum (read port)))
(unless (eof-object? datum)
(format #t "~A: ~A\n"
datum
(or (any (check-type datum) *type-list*) "other type"))
(loop (read port)))))))
以下の実行例は,Guileデータを適当に含んだファイル(data.txt)に対して上記のプログラムを実行しています.
$ cat data.txt
123.456 #\あ "ガイル" Guile #:kwd (a . b) (1 2 3 4) #(1 2 3) #*0011
$ guile -s show-type.scm data.txt
...... コンパイルメッセージ ......
123.456: number?
あ: char?
ガイル: string?
Guile: symbol?
#:kwd: keyword?
(a . b): pair?
(1 2 3 4): list?
#(1 2 3): vector?
#*0011: other type
補足
標準入力に対して read を実行したとき,Ctrl-D を押下すると read は end of file オブジェクトを返します.以下は,REPLにおいて実行した read に対して Ctrl-D を押下した場合を示しています.
guile> (read)
(ここで Ctrl-D を押下しています)
$1 = #<eof>