Function READ, READ-PRESERVING-WHITESPACE
read &optional input-stream eof-error-p eof-value recursive-p => object
read-preserving-whitespace &optional input-stream eof-error-p eof-value recursive-p => object
input-stream - 入力ストリームの指定子
eof-error-p - generalized-boolean。デフォルトはtrue。
eof-value - オブジェクト。デフォルトはnil。
recursive-p - generalized-boolean。デフォルトはfalse。
object - オブジェクト(Lispリーダーによって読み込まれたもの)か、eof-value
readは、input-streamから オブジェクトの印刷表現を構文解析し、 そのようなオブジェクトを構築します。 read-preserving-whitespaceはreadと似ていますが、 印刷表現されたオブジェクトを区切っている どのような空白文字も保護します。 read-preserving-whitespaceは、 read-preserving-whitespace自身の引数recursive-pがtrueのときは、 正確にreadのように動作します。
*read-suppress*がfalseのとき、 readは印刷表現として要求されている特定の区切り文字である 空白文字のときはそれを捨てます。 しかし、readは それが構文として意味を持つ場合は、 次の式の開始に使用できるようにするために、 その空白文字を保護します(unread-charで使用されます)。
もしシンボルか数のあとにすぐファイルの終わりが続いたとき、 readはそのシンボルか数の読み込みは成功します。 そして再び呼び出されたときにファイルの終わりが発生し、 ただeof-error-pに従い動作します。 もしファイルの終端に例えば空行やコメントなどの 無視できるテキストが含まれていたとき、 readはそれをオブジェクトの途中で終了したとはみなしません。
もしrecursive-pがtrueの場合、 readの呼び出しは トップレベルからのものではなく、 それ自身がreadから呼び出されるような何らかの内部関数であるか、 あるいは似たような入力関数で構成されることが期待されます。
両関数はinput-streamから読み込んだオブジェクトを返却します。 もしeof-error-pがfalseであり、 オブジェクトの開始より前にファイルの終わりに到達したときは、 eof-valueが返却されます。
(read)
>> 'a
=> (QUOTE A)
(with-input-from-string (is " ") (read is nil 'the-end)) => THE-END
(defun skip-then-read-char (s c n)
(if (char= c #\{) (read s t nil t) (read-preserving-whitespace s))
(read-char-no-hang s)) => SKIP-THEN-READ-CHAR
(let ((*readtable* (copy-readtable nil)))
(set-dispatch-macro-character #\# #\{ #'skip-then-read-char)
(set-dispatch-macro-character #\# #\} #'skip-then-read-char)
(with-input-from-string (is "#{123 x #}123 y")
(format t "~S ~S" (read is) (read is)))) => #\x, #\Space, NIL例として、次のリーダーマクロの定義を考えます。
(defun slash-reader (stream char)
(declare (ignore char))
`(path . ,(loop for dir = (read-preserving-whitespace stream t nil t)
then (progn (read-char stream t nil t)
(read-preserving-whitespace stream t nil t))
collect dir
while (eql (peek-char nil stream nil nil t) #\/))))
(set-macro-character #\/ #'slash-reader)ここで、次の式に対してreadを呼び出すことを考えます。
(zyedh /usr/games/zork /usr/games/boggle)マクロ/は、複数の/文字によって分割されたオブジェクトを読み込むので、 /usr/games/zorkは、(path usr games zork)のように読み込まれます。 したがって例の全体の式は、次のように読み込まれます。
(zyedh (path usr games zork) (path usr games boggle))しかし、もしreadが read-preserving-whitespaceの代わりに使用されたとき、 シンボルzorkを読み込んだ後に続く空白は切り捨てられます。 次にpeek-charが呼ばれたときは続く/を見るので、 繰り返しは継続し、次のように解釈されます。
(zyedh (path usr games zork usr games boggle))これは空白が切り捨てられたときのものです。 もしインタープリターのコマンドが単一の文字のコマンドを受け取り さらなるオブジェクトの読み込みがあるとき、 シンボルの後の空白文字を切り捨てないときは、 そのシンボルが読み込まれた後にコマンドが解釈されるかもしれません。
*standard-input*, *terminal-io*, *readtable*, *read-default-float-format*, *read-base*, *read-suppress*, *package*, *read-eval*
readは、オブジェクトの表現の最中にファイルが終わったときは、 eof-error-pに関係なく型end-of-fileのエラーが通知されます。 例えば、あるファイルから読み込まれるオブジェクト内ににおいて、 左かっこに対応するはずの十分な右かっこが含まれていなかったときは、 readはエラーを通知します。 これは、 readかread-preserving-whitespaceが呼び出されるとき、 recursive-pとeof-error-pがnilではなく、 あるオブジェクトの開始前にファイルの終わりに到達したときに 検出されます。
eof-error-pがtrueのとき、 ファイルの終わりにて型end-of-fileのエラーが通知されます。
peek-char, read-char, unread-char, read-from-string, read-delimited-list, parse-integer, 2. 構文, 23.1. リーダーの説明
なし。