21.1 Стандартные потоки

В Lisp’овой системе есть несколько переменных, значения которых являются потоками, используемыми большим количеством функций. Эти переменные и их использование описаны ниже. По соглашению, переменные, которые содержат поток для чтения, имеют имена заканчивающиеся на -input, и переменные, которые содержат поток для записи, имеют имена, заканчивающиеся на -output. Имена переменных, содержащих потоки и для чтения, и для записи, заканчиваются на -io.

[Переменная] *standard-input*

В обычном Lisp’овом цикле взаимодействия с пользователем, входные данные читаются из *standard-input* (то есть, из потока, который является значением глобальной переменной *standard-input*). Большинство функций, включая read и read-char, принимают аргумент — поток, который по-умолчанию *standard-input*.


[Переменная] *standard-output*

В обычном Lisp’овом цикле взаимодействия с пользователем, выходные данные посылаются в *standard-output* (то есть, в поток, который является значением глобальной переменной *standard-output*). Большинство функций, включая print и write-char, принимают аргумент – поток, который по-умолчанию *standard-output*.


[Переменная] *error-output*

Значение *error-output* является потоком, в который должны посылаться сообщения об ошибках. Обычно значение совпадает с *standard-output*, но *standard-output* может быть связан с файлов и *error-output* остаётся направленной на терминал или отдельный файл для сообщений об ошибках.


[Переменная] *query-io*

Значение *query-io* является потоком, используемым, когда необходимо получить от пользователя ответ на некоторый вопрос. Вопрос должен быть выведен в этот поток, и ответ из него прочитан. Когда входной поток для программы может производится из файла, вопрос «Вы действительно хотите удалить все файлы в вашей директории?» никогда не должен посылаться напрямую к пользователю. И ответ должен прийти от пользователя, а не из данных файла. Поэтому в этих целях, вместо *standard-input* и *standard-output*, должен использоваться *query-io* с помощью функции yes-or-no-p.


[Переменная] *debug-io*

Значение *debug-io* является потоком, используемым для интерактивной отладки. Часто может совпадать с *query-io*, но это необязательно.


[Переменная] *terminal-io*

Значение *terminal-io* является потоком, который соединён с пользовательской консолью. Обычно, запись в этот поток выводит данные на экран, например, а чтение из потока осуществляет чтение ввода с клавиатуры.

Когда стандартные функции, такие как read и read-char используются с этим потоком, то происходит копирование входных данных обратно в поток или «эхо». (Способ, с помощью которого это происходит, зависит от реализации.)


[Переменная] *trace-output*

Значение *trace-output* является потоком, в который функция trace выводит информацию.


Переменные *standard-input*, *standard-output*, *error-output*, *trace-output*, *query-io* и *debug-io* первоначально связаны с потоками-синонимами, которые направляют все операции в поток *terminal-io*. (Смотрите make-synonym-stream.) Таким образом все проделанные операции на этих потоках отобразятся на терминале.

X3J13 voted in January 1989 to replace the requirements of the preceding paragraph with the following new requirements:

The seven standard stream variables, *standard-input*, *standard-output*, *query-io*, *debug-io*, *terminal-io*, *error-output*, and *trace-output*, are initially bound to open streams. (These will be called the standard initial streams.)

The streams that are the initial values of *standard-input*, *query-io*, *debug-io*, and *terminal-io* must support input.

The streams that are the initial values of *standard-output*, *error-output*, *trace-output*, *query-io*, *debug-io*, and *terminal-io* must support output.

None of the standard initial streams (including the one to which *terminal-io* is initially bound) may be a synonym, either directly or indirectly, for any of the standard stream variables except *terminal-io*. For example, the initial value of *trace-output* may be a synonym stream for *terminal-io* but not a synonym stream for *standard-output* or *query-io*. (These are examples of direct synonyms.) As another example, *query-io* may be a two-way stream or echo stream whose input component is a synonym for *terminal-io*, but its input component may not be a synonym for *standard-input* or *debug-io*. (These are examples of indirect synonyms.)

Any or all of the standard initial streams may be direct or indirect synonyms for one or more common implementation-dependent streams. For example, the standard initial streams might all be synonym streams (or two-way or echo streams whose components are synonym streams) to a pair of hidden terminal input and output streams maintained by the implementation.

Part of the intent of these rules is to ensure that it is always safe to bind any standard stream variable to the value of any other standard stream variable (that is, unworkable circularities are avoided) without unduly restricting implementation flexibility.

Пользовательская программа не должна изменять значение *terminal-io*. Программа, которая, например, хочет перенаправить вывод в файл, должна изменить значение переменной *standard-output*. В таком случае, сообщения об ошибках будут продолжать посылаться в *error-output*, а следовательно в *terminal-io*, и пользователи сможет их увидеть.