テキストを読み込むためのLisp関数の多くは、入力ストリームを引数として取ります。入力ストリームは、読み込むテキストの文字をどこで、あるいはどのように取得するかを指定します。入力ストリームとして指定可能な型は以下の通りです。
入力文字は buffer から、ポイントの直後の文字を先頭として読み込まれます。文字が読み込まれるにつれて、ポイントは進みます。
入力文字は、marker が含まれるバッファから、マーカーの直後の文字を先頭として読み込まれます。文字が読み込まれるにつれて、マーカーの位置が進みます。ストリームがマーカーである場合、バッファ内の point の値は影響しません。
入力文字は string から取得され、文字列の先頭文字から始まり、必要な数だけ文字が使用されます。
入力文字はfunctionによって生成され、このタグは2種類の呼び出しをサポートする必要があります。
t ¶t
をストリームとして使用する場合、入力はミニバッファから読み込まれます。実際には、ミニバッファが一度呼び出され、ユーザーが指定したテキストが文字列に変換され、それが入力ストリームとして使用されます。Emacs
がバッチモードで動作している場合(バッチモードを参照)、ミニバッファの代わりに標準入力が使用されます。例えば、
(message "%s" (read t))
バッチモードでは、標準入力からLisp式を読み込み、その結果を標準出力に出力します。
nil ¶nil が入力ストリームとして指定された場合は、代わりに standard-input の値を使用することになります。その値は デフォルト入力ストリーム であり、nil
以外の入力ストリームである必要があります。
入力ストリームとしてのシンボルは、そのシンボルの関数定義(もしあれば)と同等である。
バッファであるストリームから読み込む例を以下に示します。前後でポイントがどこにあるかを示しています。
---------- Buffer: foo ---------- This∗ is the contents of foo. ---------- Buffer: foo ----------
(read (get-buffer "foo"))
⇒ is
(read (get-buffer "foo"))
⇒ the
---------- Buffer: foo ---------- This is the∗ contents of foo. ---------- Buffer: foo ----------
なお、最初の読み込みではスペースがスキップされます。読み込み時には、重要なテキストに先行する任意の量の空白がスキップされます。
以下に、最初は表示されているバッファの先頭に配置されたマーカーであるストリームから読み込む例を示します。読み出された値はシンボル This です。
---------- Buffer: foo ---------- This is the contents of foo. ---------- Buffer: foo ----------
(setq m (set-marker (make-marker) 1 (get-buffer "foo")))
⇒ #<marker at 1 in foo>
(read m)
⇒ This
m
⇒ #<marker at 5 in foo> ;; Before the first space.
ここでは、文字列の内容から読み取りを行います:
(read "(When in) the course")
⇒ (When in)
以下の例では、ミニバッファから読み込みを行います。プロンプトは ‘Lisp expression: ’ です。(これは、ストリーム t から読み込む際に常に使用されるプロンプトです。)ユーザーの入力は、プロンプトの後に表示されます。
(read t)
⇒ 23
---------- Buffer: Minibuffer ----------
Lisp expression: 23 RET
---------- Buffer: Minibuffer ----------
最後に、useless-stream
という名前の関数であるストリームの例を示します。ストリームを使用する前に、変数 useless-list を文字のリストで初期化します。その後、関数 useless-stream
が呼び出されるたびに、リスト内の次の文字を取得するか、あるいは文字をリストの先頭に追加して未読状態にします。
(setq useless-list (append "XY()" nil))
⇒ (88 89 40 41)
(defun useless-stream (&optional unread)
(if unread
(setq useless-list (cons unread useless-list))
(prog1 (car useless-list)
(setq useless-list (cdr useless-list)))))
⇒ useless-stream
それでは、このように構築したストリームを用いて読み込みます:
(read 'useless-stream)
⇒ XY
useless-list
⇒ (40 41)
なお、リストには開き括弧と閉じ括弧がそのまま残っている点に注意してください。Lispリーダーは開き括弧を検出し、それが入力の終端であると判断して、読み飛ばしました。この時点でストリームから再度読み込もうとすると、‘()’が読み込まれ、nilが返されます。