Input and Output

## 4.5 Input and Output

- Printing ECLiPSe Terms
- Reading ECLiPSe Terms
- Formatted Output
- Streams

### 4.5.1 Printing ECLiPSe Terms

> write(+Stream, ?Term) write one term in a default format. write_term(+Stream, ?Term, +Options) write one term, format options can be selected. printf(+Stream, +Format, +ArgList) write a string with embedded terms, according to a format string. writeq(+Stream, ?Term), write_canonical(+Stream, ?Term) write one term so that it can be read back. put(+Stream, +Char) write one character.

> Figure 4.3: Builtins for writing

The predicates of the write-group are generic in the sense that they can print any ECLiPSe data structure. The different predicates print slightly different formats. The `write/1` predicate is intended to be most human-readable, while `writeq/1` is designed so that the printed data can be read back by the predicates of the read-family. If we print the structured term `foo(3+4, [1,2], X, 'a b', "string")` the results are as follows:

>     write:             foo(3 + 4, [1, 2], X, a b, string)
>     writeq:            foo(3 + 4, [1, 2], _102, 'a b', "string")

The write-format is the shortest, but some information is missing, e.g. that the sequence `a b` is an atomic unit and that `string` is a string and not an atom. The writeq-format quotes items properly, moreover, the variables are printed with unique numbers, so different variables are printed differently and identical ones identically.
Single characters, encoded in ascii, can be output using `put/1`, for example:

>     [eclipse: 1] put(97).
>     a
>     yes.

### 4.5.2 Reading ECLiPSe Terms

> read(+Stream, -Term) read one fullstop-terminated ECLiPSeterm. read_term(+Stream, -Term, +Options) read one fullstop-terminated ECLiPSeterm. get(+Stream, -Char) read one character. read_string(+Stream, +Terminator, -Length, -String) read a string up to a certain terminator character. read_token(+Stream, -Token, -Class) read one syntactic token (e.g. a number, an atom, a bracket, etc).

> Figure 4.4: Builtins for reading

If the data to be read is in Prolog syntax, it can be read using `read(?Term)`. This predicate reads one fullstop-terminated ECLiPSeterm from stream Stream. A fullstop is defined as a dot followed by a layout character like blank space or newline. Examples:

>     [eclipse 4]: read(X).
>      123,a.
>     X = 123, a
>     yes.

>     [eclipse 6]: read(X).
>      [3,X,foo(bar),Y].
>     X = [3, X, foo(bar), Y]
>     yes.

Single characters can be input using `get/1`, which gets their ascii encoding, for example:

>     [eclipse: 1] get(X).
>     a
>     X=97
>     yes.

### 4.5.3 Formatted Output

The printf-predicate is similar to the printf-function in C, with some ECLiPSe-specific format extensions. Here are some examples of printing numbers:

>     ?- printf("%d", [123]).
>     123
>     yes.
>     ?- printf("%5d,%05d", [123,456]).
>       123,00456
>     yes.
>     ?- printf("%6.2f", [123]).
>     type error in printf("%6.2f", [123])
>     ?- printf("%6.2f", [123.4]).
>     123.40
>     yes.
>     ?- printf("%6.2f", [12.3]).
>      12.30
>     yes.

The most important ECLiPSe-specific format option is %w, which allows to print like the predicates of the write-family:

>     ?- printf("%w", [foo(3+4, [1,2], X, 'a b', "string")]).
>     foo(3 + 4, [1, 2], X, a b, string)

The %w format allows a number of modifiers in order to access all the existing options for the printing of ECLiPSe terms.

⊙
  For details see the write_term/2 and printf/2 predicates.

### 4.5.4 Streams

ECLiPSe I/O is done from and to named channels called streams. The following streams are always opened when ECLiPSe is running: input (used by the input predicates that do not have an explicit stream argument, e.g. read/1 ), output (used by the output predicates that do not have an explicit stream argument, e.g. write/1 ), error (output for error messages and all messages about exceptional states ), warning_output (used by the system to output warning messages ), log_output (used by the system to output log messages, e.g. messages about garbage collection activity ), null ( a dummy stream, output to it is discarded, on input it always gives end of file).
Data can be read from a specific stream using read(+Stream, ?Term), and written to a specific stream using write(+Stream, ?Term). If no particular stream is specified, input predicates read from input and output predicates write to output.
New streams may be opened onto various I/O devices, see figure 4.5.

> I/O device | How to open
> tty | implicit (stdin,stdout,stderr) or open/3 of a device file
> file | open(FileName, Mode, Stream)
> string | open(string(String), Mode, Stream)
> queue | open(queue(String), Mode, Stream)
> pipe | exec/2, exec/3 and exec_group/3
> socket | socket/3 and accept/3
> null | implicit (null stream)

> Figure 4.5: How to open streams onto the different I/O devices

All types of streams are closed using close(+Stream).

⊙
  See the complete description of the stream-related built-in predicates in the Reference Manual

For network communication over sockets, there is a full set of predicates modelled after the BSD socket interface: socket/3, accept/3, bind/2, listen/2, select/3. See the reference manual for details.
Output in ECLiPSe is usually buffered, i.e. printed text goes into a buffer and may not immediately appear on the screen, in a file, or be sent via a network connection. Use flush(+Stream) to empty the buffer and write all data to the underlying device.