ポート(port)
ポート(port)
入出力処理は,ファイルだけでなく,標準入力,標準出力,標準エラー出力,
文字列オブジェクト,バイトベクタオブジェクト,
ネットワークなどの様々な対象に対して行うことができます.
それらの入出力は,一般にポートと呼ばれるオブジェクトを介して行います.
筆者が調べた範囲で言うと,例えばファイルを対象とするポート(ファイルポート)は,
ファイルディスクリプタやファイル名や入出力用バッファなどから構成された構造体として定義されています.でも,Schemeでプログラミングするにあたって,
ポートの内部構造を詳しく理解していなくても(たぶん)大丈夫です.
ポートは,直感的に,それぞれの処理対象に付けた出入口または通路のようなものと理解しておけばよいと思います.
入出力処理の仕方は処理対象に関係なく共通していて,
-
処理対象を開いてポートを生成し,
-
ポートを介して入出力を行ったあと,
-
ポートを閉じて入出力処理を終える
といった手順で行います.
ファイルポート(file port)
Schemeでは,ファイルへのあらゆる入出力はファイルポート(ファイルを処理対象とするポート)を介して行います.
以後,ファイルを処理対象にしていることが明らかな文脈では,
「ファイルポート」を略して単に「ポート」と呼ぶことがあります.
Schemeにおけるファイルの入出力は,大まかに,次の手順で行います.
- ファイルをオープンしてファイルポートを生成する.
- そのファイルポートを介して入出力を行う.
- 最後に,ファイルポートをクローズして入出力処理を終了する.
ここで,「ファイルを開いてファイルポートを生成する」とは,ファイルに出入口を付けて,入出力が可能な状態にすることを言います.この処理を手続きで行うときには「ファイルを開いてファイルポートを返す」と言ったりもします.
さらに,「ファイルポートを閉じる」とは,ファイルに付けている出入口を閉じることを言います.
ファイルを開く際には,その入出力処理に関して,
少なくとも以下に示すような項目(処理の目的)を指定します.
-
入力,出力,追加出力,入出力のどれを行うのか.
-
テキストモード(テキストデータとして処理する)か,
バイナリモード(バイナリデータとして処理する)か.
ファイルを開くとき,これらの処理目的を属性値とするファイルポートが生成されます.
ファイルポートは生成時の処理目的に沿った使い方をしなければいけません.
そうしないとき,エラーが発生したり,おかしな結果が生じたりします.
例えば,入力用のファイルポートに対して出力を行うとエラーが発生します.
また,バイナリモードで生成したファイルポートから得たデータをテキストデータとして処理したとき,文字化けが生じたりします.
ファイルポートを閉じたあと,そのファイルポートを再利用するための手続きはありません.閉じたあとのファイルポートを使おうとするとエラーが発生します.つまり,ファイルポートは1回限りの使い捨てオブジェクトです.ファイルに対して入出力を行うときには,
上で述べた手順を毎回行わなければなりません.
「現在」の入出力用のポート
Guileは,REPLを起動したりスクリプトを処理する際に,
カレント入力ポート(current input port),
カレント出力ポート(current output port),
カレントエラーポート(current error port)という3つのポートを設定します.
それぞれの初期値(デフォルト)は,システムの標準入力(通常,キーボード),
標準出力(通常,端末),標準エラー出力(通常,端末)です.
入出力を行う手続きでポートを指定しなかった場合,これらのポートが使用されます.
例えば,display 手続きや write 手続きを実行するときにポートを指定しないことが多いと思いますが,そのような場合,カレント出力ポート(通常,端末)に出力されます.
これらの値を変更することもできます.
例えば,カレント出力ポートをファイルポートに変えることができます.
その場合,カレント出力ポートへの出力は,ファイルポートに接続しているファイルに行われることになります.
ポートに関連する手続き
procedure:
(port? obj)
(input-port? obj)
(output-port? obj)
(file-port? obj)
(port-closed? port)
port |
ポートオブジェクト |
obj |
任意のオブジェクト |
返り値 |
ブール値 |
port? 手続きは,obj がポートオブジェクトの場合 #t を返し,そうでない場合 #f を返します.
input-port? 手続きは,obj が入力用のポートオブジェクトの場合 #t を返し,そうでない場合 #f を返します.
output-port? 手続きは,obj が出力用のポートオブジェクトの場合 #t を返し,そうでない場合 #f を返します.
file-port? 手続きは,obj がファイルポートの場合 #t を返し,そうでない場合 #f を返します.
port-closed? 手続きは,port が閉じている場合 #t を返し,そうでない場合 #f を返します.port がポートオブジェクトでない場合,エラーが発生します.
procedure:
(port-filename port)
port |
ポートオブジェクト |
返り値 |
文字列(ファイル名) |
この手続きはポート(port)に関連付けられているファイル名を返します.
そういったファイルがない場合,#f を返します.
この手続きを実行するとき,port はオープンしていなければいけません.
一度クローズした port に対して実行するとエラーが発生します.
procedure:
(current-input-port)
(current-output-port)
(current-error-port)
これらの手続きは,それぞれ,カレント入力ポート,カレント出力ポート,カレントエラーポートを返します.
システム起動時に,上記のポートは,ぞれぞれ,標準入力,標準出力,標準エラーに束縛されます.さらに,これらが端末の場合には,バッファリングはされません.
procedure:
(set-current-input-port port)
(set-current-output-port port)
(set-current-error-port port)
port |
ポートオブジェクト |
返り値 |
変更前のポートオブジェクト |
これらの手続きは,それぞれ,カレント入力ポート,カレント出力ポート,カレントエラーポートを port に設定します.
Guile[6.12.9 Default Ports for Input, Output and Errors] には返り値に関する記述がないのですが(そして,残念なことに,ソースコードを見ても筆者には理解出来ないのですが),以下の簡単な実験をしてみると,変更前のポートオブジェクトを返すようです.
;; current-port.scm
(define fport (open-output-file "temp.txt"))
(define cport0 (current-output-port))
(define cport1 (set-current-output-port fport))
(define cport2 (set-current-output-port cport0))
(format #t "fport is ~A\n" fport)
(format #t "cport0 is ~A\n" cport0)
(format #t "(set-current-output-port fport) returns ~A\n" cport1)
(format #t "(set-current-output-port cport0) returns ~A\n" cport2)
(close-port fport)
guile> (load "current-port.scm")
...... コンパイルメッセージ ......
fport is #<output: temp.txt 14>
cport0 is #<output: file /dev/pts/2>
(set-current-output-port fport) returns #<output: file /dev/pts/2>
(set-current-output-port cport0) returns #<output: temp.txt 14>
$1 = #t
current-output-port を fport に設定したときには,変更前の cport0 が返ってきていて,cport0 に設定し直したときには fport が返ってきています.
ファイルのオープンとクローズ(概要)
ファイルポートをクローズする手続きは1つしかありません.
実際,それはファイルポートに限らず,あらゆるポートをクローズするために使用します.
以下では,1つしかないので,ポートをクローズする手続きを最初に説明します.
ファイルをオープンする手続きは幾つかあり,次の4つのレベルに分かれます.
- open-file
これはもっとも基本的な手続きです.引数を通して処理目的を細かく指定できます.
- open-input-file と open-output-file
これらは入力用または出力用に特化した手続きです.
これらは open-file を使って定義されています.
- call-with-input-file と call-with-output-file
これらは,ファイル名を指定するだけで,
ファイルポートを生成する処理とクローズする処理を自動的に行ってくれます.
- with-input-from-file と with-output-to-file
これらは,
ファイル名とカレント入力ポートやカレント出力ポートへの入出力処理を指定するだけで,
その入出力処理をファイルに対して行ってくれます.ファイルポートの生成やクローズを行う必要はありません.
以下では,open-file を最後に説明します.
なぜなら,それを使う機会がもっとも少ないと思われるからです.
close-port
procedure:
(close-port port)
この手続きは,port に指定されたポートを閉じます.
出力用のポートの場合,
バッファに溜まっているすべてのデータをファイルに書き出します.
無事閉じることができたら #t を返し,ポートがすでに閉じていたら #f を返します.
ポートを閉じている間にエラーが生じて例外を発生させることもあります.
open-input-file と open-output-file
procedure:
(open-input-file filename [#:binary bin]
[#:guess-encoding guess-enc]
[#:encoding enc])
filename |
文字列(ファイルのパス名) |
bin |
ブール値.省略時は #f に設定されます. |
guess-enc |
ブール値.省略時は #f に設定されます. |
enc |
文字列(文字エンコーディング名).省略時は #f に設定されます. |
返り値 |
入力用のファイルポート |
注意
-
上記の角括弧 [ ... ] は省略可能であることを示しています.
手続き呼び出しの構文要素ではありません.
-
キーワード引数は順不同です.
この手続きは,filename に指定したファイルを入力用にオープンし,入力用のファイルポートを返します.
キーワード引数の #:binary bin は,
ファイルをテキストモードでオープンするか,バイナリモードでオープンするかを指定するために使用します.テキストモードでオープンしたい場合,#:binary bin を省略するか bin に #f を指定します.バイナリモードでオープンしたい場合,bin に #t を指定します.
キーワード引数の #:guess-encoding guess-enc と #:encoding enc は,テキストモードでオープンした場合の文字エンコーディング(いわゆる文字コード)を指定するために使用します.後ほど,Guile による文字エンコーディングの決め方について説明します.これらのキーワード引数の値は,その説明に合わせて指定します.
enc は,IANA Character Sets が定めたエンコーディング名を指定します.
広く知られている名前として,例えば,"utf-8" や "iso-8859-1" などがあります.
なお IANA Character Sets の説明文の中に,エンコーディング名に関して
「no distinction is made between use of upper and lower case letters.」
とあるので,エンコーディング名は小文字でも大文字でも構わないと思われます.
エラー
ファイルをバイナリーモードでオープンし,かつ,guess-enc や enc を指定した場合,エラーが発生します.
正確に言うと,guess-enc に #f を指定してもエラーは発生しないようですが,無意味です.
文字エンコーディング
ファイルをテキストモードでオープンした場合,guess-enc と enc の値に基づいて,Guileは次のように文字エンコーディングを決定します.
-
guess-enc が真値(#f 以外の値)だった場合,file-encoding 手続きを使って文字エンコーディングを推定し,その推定結果を使用します.
-
guess-enc が #f かまたは file-encoding 手続きによる推定が失敗した場合,enc に指定された文字エンコーディングを使用します.
-
guess-enc や enc を省略した場合や,以上の処理が何らかの理由によって失敗した場合,
デフォルトの文字エンコーディングを使用します.
デフォルトの文字エンコーディング
デフォルトの文字エンコーディングの決め方については,マニュアルから読み取れません(たぶん,説明していないと思います).ただ,libguile/ports.c の中の scm_init_ports 関数の中に次のような断片があります.
/* Use the locale as the default port encoding. */
scm_i_set_default_port_encoding (locale_charset ());
確信はありませんが,この記述より,デフォルトの文字エンコーディングはシステムロケールの文字エンコーディングだろうと推測します.例えば,筆者のシステム(日本語環境のDebian 11;ロケールは ja_JP.UTF-8)の場合,UTF-8 だろうと思います.
具体例
以下のプログラムは,このhtmlファイルの先頭から10行を行番号を付けて表示します.
下記の (ice-9 textual-ports) モジュールは,
テキストファイルの入出力を行う手続き(下記の get-line など)を使うためのものです.
;; open-close.scm
(use-modules (ice-9 textual-ports))
(let ((inport (open-input-file "open-close.html")))
(let loop ((k 1))
(when (<= k 10)
(format #t "~A: ~A\n" k (get-line inport))
(loop (1+ k))))
(close-port inport))
guile> (load "open-close.scm")
...... コンパイルメッセージ ......
1: <!DOCTYPE html>
2: <html lang="ja">
3: <head>
4: <meta charset="UTF-8">
5: <meta name="viewport" content="width=device-width, initial-scale=1">
6: <title>AlgoKajya Guile基礎/テキストファイルの入出力</title>
7: <link rel="stylesheet" type="text/css" href="../../guilenew.css">
8: <!-- %%% MathJax %%% -->
9: <!--
10: <script src="https://polyfill.io/v3/polyfill.min.js?features=es6"></script>
$1 = #t
最後の $1 = #t は let 式の返り値ですが,
それは close-port 手続きの返り値です.
参考
この手続きは,(ice-9 ports) モジュールの中で次のように定義されています.
(define* (open-input-file file #:key (binary #f)
(guess-encoding #f)
(encoding #f))
(open-file file (if binary "rb" "r")
#:guess-encoding guess-encoding)
#:encoding encoding)
なお,open-file 手続きについては,このノートのうしろのほうで説明します.
procedure:
(open-output-file filename [#:binary bin]
[#:encoding enc])
filename |
文字列(ファイルのパス名) |
bin |
ブール値.省略時は #f に設定されます. |
enc |
文字列(文字エンコーディング名).省略時は #f に設定されます. |
返り値 |
出力用のファイルポート |
注意
-
上記の角括弧 [ ... ] は省略可能であることを示しています.
手続き呼び出しの構文要素ではありません.
-
キーワード引数は順不同です.
この手続きは,filename に指定したファイルを出力用にオープンし,出力用のファイルポートを返します.
キーワード引数の #:binary bin は,
ファイルをテキストモードでオープンするか,バイナリモードでオープンするかを指定するために使用します.テキストモードでオープンしたい場合,#:binary bin を省略するか bin に #f を指定します.バイナリモードでオープンしたい場合,bin に #t を指定します.
キーワード引数の #:encoding enc は,出力する文字列データの文字エンコーディングを指定するために使用します.これを省略した場合,Guile は,
デフォルトの文字エンコーディングを使用します.enc に指定できる値やデフォルトの文字エンコーディングについては,open-input-file の場合とまったく同じです.
具体例
以下のプログラムは,前に示したものを少し変更したものです.
このhtmlファイルの先頭から10行(行番号付き)を標準出力に表示する代わりに,
テキストファイル(temp.txt)に出力しています.
前のプログラムから変化した部分を色分けして示しています.
(use-modules (ice-9 textual-ports))
(let ((inport (open-input-file "open-close.html"))
(outport (open-output-file "temp.txt")))
(let loop ((k 1))
(when (<= k 10)
(format outport "~A: ~A\n" k (get-line inport))
(loop (1+ k))))
(close-port inport)
(close-port outport))
guile> (load "open-close.scm")
...... コンパイルメッセージ ......
$1 = #t
今回はlet式の返り値($1 = #t)以外に何も表示されません.
以下に実行後のテキストファイル(temp.txt)の内容を示します.
$ cat temp.txt
1: <!DOCTYPE html>
2: <html lang="ja">
3: <head>
4: <meta charset="UTF-8">
5: <meta name="viewport" content="width=device-width, initial-scale=1">
6: <title>AlgoKajya Guile基礎/テキストファイルの入出力</title>
7: <link rel="stylesheet" type="text/css" href="../../guilenew.css">
8: <!-- %%% MathJax %%% -->
9: <!--
10: <script src="https://polyfill.io/v3/polyfill.min.js?features=es6"></script>
参考
この手続きは,(ice-9 ports) モジュールの中で次のように定義されています.
(define* (open-output-file file #:key (binary #f) (encoding #f))
(open-file file (if binary "wb" "w")
#:encoding encoding))
なお,open-file 手続きについては,このノートのうしろのほうで説明します.
call-with-input-file と call-with-output-file
procedure:
(call-with-input-file filename proc [#:binary bin]
[#:guess-encoding guess-enc]
[#:encoding enc])
filename |
文字列(ファイルのパス名) |
proc |
ポートを引数とする手続き |
bin |
ブール値.省略時は #f に設定されます. |
guess-enc |
ブール値.省略時は #f に設定されます. |
enc |
文字列(文字エンコーディング名).省略時は #f に設定されます. |
返り値 |
手続き proc の返り値をそのまま返します. |
注意
-
上記の角括弧 [ ... ] は省略可能であることを示しています.
手続き呼び出しの構文要素ではありません.
-
キーワード引数は順不同です.
-
proc は,多値を返す手続きでもかまいません.
この手続きは,filename で指定されたファイルを入力用にオープンしてファイルポートを生成し,そのファイルポートに対して proc を適用します.
proc が終了すると,ファイルポートを自動的に閉じて,proc の返り値をそのまま返します.
ただし,proc の中で継続を実行するなどして call-with-input-file の処理を中断した場合,ポートは自動的にはクローズされません.従って,明示的に処理を中断する可能性がある場合,ファイルポートを閉じる処理を中断処理の中に組み込まなければいけません.
キーワード引数の意味(機能)は open-input-file とまったく同じです.
具体例
以下のプログラムは,open-input-file のところで示したものを,call-with-input-file を使って作り直したものです.繰り返し処理はまったく変更していませんが,それ以外のところは大きく変わっています.実行例は,まったく同じなので,省略します.
(use-modules (ice-9 textual-ports))
(call-with-input-file "open-close.html"
(lambda (inport)
(let loop ((k 1))
(when (<= k 10)
(format #t "~A: ~A\n" k (get-line inport))
(loop (1+ k))))))
参考
call-with-input-file は (ice-9 ports) モジュールの中で次のように定義されています.
これを見ると proc は多値を返す手続きでもよいことが分かります.
(define* (call-with-input-file
file proc #:key (binary #f) (encoding #f) (guess-encoding #f))
(let ((p (open-input-file file
#:binary binary
#:encoding encoding
#:guess-encoding guess-encoding)))
(call-with-values
(lambda () (proc p))
(lambda vals
(close-input-port p)
(apply values vals)))))
なお,Guile 3.0.6 以降では,call-with-port が定義され,call-with-input-file はそれを用いて定義されています.
procedure:
(call-with-output-file filename proc [#:binary bin]
[#:encoding enc])
filename |
文字列(ファイルのパス名) |
proc |
ポートを引数とする手続き. |
bin |
ブール値.省略時は #f に設定されます. |
enc |
文字列(文字エンコーディング名).省略時は #f に設定されます. |
返り値 |
手続き proc の返り値をそのまま返します. |
注意
-
上記の角括弧 [ ... ] は省略可能であることを示しています.
手続き呼び出しの構文要素ではありません.
-
キーワード引数は順不同です.
-
proc は,多値を返す手続きでもかまいません.
この手続きは,filename で指定されたファイルを出力用にオープンしてファイルポートを生成し,そのファイルポートに対して proc を適用します.
proc が終了すると,ファイルポートを自動的に閉じて,proc の返り値をそのまま返します.
proc の中で継続を実行するなどして処理を中断したが場合,
ファイルポートは自動的にクローズされないので,
クローズ処理を中断処理の中に組み込まなければなりません.
そうしないとバッファに溜まっている出力は,
ファイルに保存されずに廃棄されるかも知れません.
具体例
以下のプログラムは,open-output-file のところで示したものを,
call-with-input-file と call-with-output-file を使って作り直したものです.
実行例は省略します.
(use-modules (ice-9 textual-ports))
(call-with-input-file "open-close.html"
(lambda (inport)
(call-with-output-file "temp.txt"
(lambda (outport)
(let loop ((k 1))
(when (<= k 10)
(format outport "~A: ~A\n" k (get-line inport))
(loop (1+ k))))))))
参考
call-with-output-file は (ice-9 ports) モジュールの中で次のように定義されています.
これを見ると proc は多値を返す手続きでもよいことが分かります.
(define* (call-with-output-file file proc #:key (binary #f) (encoding #f))
(let ((p (open-output-file file #:binary binary #:encoding encoding)))
(call-with-values
(lambda () (proc p))
(lambda vals
(close-output-port p)
(apply values vals)))))
なお,Guile 3.0.6 以降では,call-with-port が定義され,call-with-output-file はそれを用いて定義されています.
with-input-from-file,with-output-to-file,with-error-to-file
procedure:
(with-input-from-file filename thunk [#:binary bin]
[#:guess-encoding guess-enc]
[#:encoding enc])
(with-output-to-file filename thunk [#:binary bin]
[#:encoding enc])
(with-error-to-file filename thunk [#:binary bin]
[#:encoding enc])
filename |
文字列(ファイルのパス名) |
thunk |
サンク |
bin |
ブール値.省略時は #f に設定されます. |
guess-enc |
ブール値.省略時は #f に設定されます. |
enc |
文字列(文字エンコーディング名).省略時は #f に設定されます. |
返り値 |
thunk の返り値をそのまま返します. |
注意
-
上記の角括弧 [ ... ] は省略可能であることを示しています.
手続き呼び出しの構文要素ではありません.
-
キーワード引数は順不同です.
with-input-from-file 手続きは,
filename に指定されたファイルをオープンしてファイルポートを生成し,そのファイルポートをカレント入力ポート(current-input-port)に設定して,
サンク(thunk)を実行します.
従って,サンクにおけるカレント入力ポートに対する処理は,
ファイルポートに対する処理になります.
例えば,カレント入力ポートからデータを入力したとき,それはファイルから入力することになります.サンクが終了したら,カレント入力ポートを元の値に戻して,
サンクの返り値をそのまま返します.
with-output-to-file 手続きは
カレント出力ポート(current-output-port)に対して同様の処理を行い,
with-error-to-file 手続きは
カレントエラーポート(current-error-port)に対して同様の処理を行います.
キーワード引数の意味(機能)は open-input-file の場合と同じです.
Guile[6.12.10.1 File Ports] における次の説明は,いまの筆者には手に余る内容なので,マニュアルの文章をそのまま引用します.
The current port setting is managed with dynamic-wind, so the previous value is restored no matter how thunk exits (eg. an exception), and if thunk is re-entered (via a captured continuation) then it’s set again to the filename port.
The port is closed when thunk returns normally, but not when exited via an exception or new continuation. This ensures it’s still ready for use if thunk is re-entered by a captured continuation. Of course the port is always garbage collected and closed in the usual way when no longer referenced anywhere.
具体例
この html ファイルの先頭10行を行番号付きで temp.txt に出力する処理を,
上記の手続きを使って作成したプログラムを示します.実行例は省略します.
(use-modules (ice-9 textual-ports))
(use-modules (ice-9 textual-ports))
(with-input-from-file "open-close.html"
(lambda ()
(with-output-to-file "temp.txt"
(lambda()
(let loop ((k 1))
(when (<= k 10)
(format #t "~A: ~A\n" k (get-line (current-input-port)))
(loop (1+ k))))))))
なお,format 手続きは第1引数に #t を指定すると,カレント出力ポートに出力します.
参考
上記の手続きは (ice-9 ports) モジュールの中で次のように定義されています.
(define* (with-input-from-file
file thunk #:key (binary #f) (encoding #f) (guess-encoding #f))
(call-with-input-file file
(lambda (p) (with-input-from-port p thunk))
#:binary binary
#:encoding encoding
#:guess-encoding guess-encoding))
(define* (with-output-to-file file thunk #:key (binary #f) (encoding #f))
(call-with-output-file file
(lambda (p) (with-output-to-port p thunk))
#:binary binary
#:encoding encoding))
(define* (with-error-to-file file thunk #:key (binary #f) (encoding #f))
(call-with-output-file file
(lambda (p) (with-error-to-port p thunk))
#:binary binary
#:encoding encoding))
open-file
procedure:
(open-file path mode [#:guess-encoding guess-enc]
[#:encoding enc])
path |
文字列(ファイルのパス名) |
mode |
文字列(アクセスモード) |
guess-enc |
ブール値.省略時は #f に設定されます. |
enc |
文字列(文字エンコーディング名).省略時は #f に設定されます. |
返り値 |
ファイルポート |
この手続きは,path で指定されたファイルをオープンし,
そのファイルデータにアクセスするためのファイルポートを返します.
ファイルは,下記のバイナリモードが指定されない限り,
テキストモードでオープンします.
またそのとき,guess-enc や enc で指定されたエンコーディングかまたはデフォルトのエンコーディングに基づいて,文字コードを認識します.
文字エンコーディングの決め方やキーワード引数については open-input-file の項を参照して下さい.
mode は,
ファイルデータへのアクセスモードを文字列によって指定します.
その文字列の1文字目は下記のいずれかを指定します.これは必須です.
1文字目 | 意味 |
r |
ファイルを入力用にオープンします.
|
w |
ファイルを出力用にオープンします.
ファイルが存在しない場合,空のファイルを新たに作成します.
ファイルが存在する場合,そのデータを消去して空にします.
|
a |
ファイルを追加用にオープンします.
ファイルが存在しない場合,空のファイルを新たに作成します.
ファイルが存在する場合,ファイルポインタをファイルデータの末尾に設定して,
追加出力ができる状態にします.
|
2文字目以降は次の文字が指定できます.これはオプションです.
2文字目以降 | 意味 |
b |
ファイルをバイナリモードでオープンします.
ファイルデータはバイト列として扱われます.
これを指定しないときにはテキストモードでオープンします.
|
+ |
ファイルを入力・出力両用にオープンします.
例えば,"r+" を指定すると,ファイルは入出力用にオープンされます.
|
0 |
バッファを使用しないポートを作成して返します.
入力・出力操作は,バッファを経由せずにファイルに対して直接行われます.
これを指定すると,一般に,入出力の性能が低下します.
しかし,アプリケーションが独自にバッファリングを行っている場合には役立つこともあるようです.
|
l |
Add line-buffering to the port.
The port output buffer will be automatically
flushed whenever a newline character is written.
これを指定すると,
改行文字が出力されるたびにバッファの内容がファイルに書き出されるようになる,
ということだと思います.
|
エラー
ファイルをバイナリーモードでオープンし,かつ,guess-enc や enc を指定した場合,エラーが発生します.
call-with-port,with-input-from-port,with-output-to-port,with-error-to-port
これまでの手続きはファイルを処理対象とするものでしたが,
すでに開いているポートを処理対象とする手続きもあります.
ただ,これらはユーザープログラムの中で使用するというよりも,
これまで述べてきた手続きを定義するために用意されたものだろうと思います.
procedure:
(call-with-port port proc)
port |
ポートオブジェクト |
proc |
ポートを引数とする手続き |
返り値 |
proc の返り値 |
この手続きは,ポート(port)に手続き(proc)を適用し,その返り値をそのまま返します.ポートはオープンしていなければいけません.
注意
この手続きは Guile 3.0.6 以降に実装されています.3.0.5 では使えません.
参考
上記の手続きは (ice-9 ports) モジュールの中で次のように定義されています.
(define (call-with-port port proc)
(call-with-values
(lambda () (proc port))
(lambda vals
(close-port port)
(apply values vals))))
procedure:
(with-input-from-port port thunk)
(with-output-to-port port thunk)
(with-error-to-port port thunk)
port |
ポートオブジェクト |
thunk |
サンク |
返り値 |
thunk の返り値 |
これらの手続きは,それぞれ,カレント入力ポート,カレント出力ポート,
カレントエラーポートを port に設定してサンク(thunk)を実行し,その返り値をそのまま返します.
参考
上記の手続きは (ice-9 ports) モジュールの中で次のように定義されています.
(define (with-input-from-port port thunk)
(parameterize ((current-input-port port))
(thunk)))
(define (with-output-to-port port thunk)
(parameterize ((current-output-port port))
(thunk)))
(define (with-error-to-port port thunk)
(parameterize ((current-error-port port))
(thunk)))