Next: , Previous: Streams Intro, Up: Read and Print


18.2 入力ストリーム

テキストを読み取るほとんどのLisp関数は、 ストリーム(stream)を引数として受け付けます。 入力ストリームは、読み取るべきテキストの文字をどこからどのように得るのかを 指定します。 入力ストリームとして使える型は以下のとおりです。

buffer
入力文字はバッファbufferのポイント直後の文字から読み取られる。 1文字読むごとにポイントを進める。
marker
入力文字は、マーカmarkerがあるバッファの マーカ直後の文字から読み取られる。 1文字読むごとにマーカ位置を進める。 ストリームがマーカであるときには、バッファのポイント位置は影響しない。
string
入力文字は文字列stringの先頭文字から必要な文字数だけ読み取られる。
function
入力文字は関数functionが生成する。 この関数は2種類の呼び出し方を扱える必要がある。
t
ストリームとしてtを使うと、ミニバッファから読み取ることを意味する。 実際には、ミニバッファを表示しユーザーが指定したテキストから成る文字列を作り、 それを入力ストリームとして使う。
nil
入力ストリームとしてnilを指定すると、 standard-inputの値をかわりに使うことを意味する。 その値はデフォルト入力ストリームであり、 nil以外の入力ストリームであること。
symbol
入力ストリームとしてのシンボルは、 そのシンボルの(あれば)関数定義と等価である。

バッファであるストリームからの読み取りの例を 読み取り前後のポイント位置を含めて示します。

     ---------- 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>   ;; 最初の空白の直前

つぎは文字列の内容から読み取ります。

     (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を返します。

— Function: get-file-char

この関数は、関数loadで開いた入力ファイルから読み取るための 入力ストリームとして内部的に使われる。 読者はこの関数を使ってはならない。