Did you know ... | Search Documentation: |
Edinburgh-style I/O |
The package for implicit input and output destinations is (almost) compatible with Edinburgh DEC-10 and C-Prolog. The reading and writing predicates refer to, resp., the current input and output streams. Initially these streams are connected to the terminal. The current output stream is changed using tell/1 or append/1. The current input stream is changed using see/1. The stream's current value can be obtained using telling/1 for output and seeing/1 for input.
Source and destination are either a file, user
, or a
term‘pipe(Command)’. The reserved stream name user
refers to the terminal.104The ISO
I/O layer uses user_input
, user_output
and user_error
.
In the predicate descriptions below we will call the source/destination
argument‘SrcDest’. Below are some examples of
source/destination specifications.
?- see(data). | % Start reading from file‘data’. |
?- tell(user). | % Start writing to the terminal. |
?- tell(pipe(lpr)). | % Start writing to the printer. |
Another example of using the pipe/1
construct is shown
below.105As of version 5.3.15, the
pipe construct is supported in the MS-Windows version, both for swipl.exe
and swipl-win.exe. The implementation uses code from the LUA
programming language (http://www.lua.org).
Note that the pipe/1
construct is not part of Prolog's
standard I/O repertoire.
getwd(Wd) :- seeing(Old), see(pipe(pwd)), collect_wd(String), seen, see(Old), atom_codes(Wd, String). collect_wd([C|R]) :- get0(C), C \== -1, !, collect_wd(R). collect_wd([]).
The effect of tell/1 is not undone on backtracking, and since the stream handle is not specified explicitly in further I/O operations when using Edinburgh-style I/O, you may write to unintended streams more easily than when using ISO compliant I/O. For example, the following query writes both "a" and "b" into the file‘out’:
?- (tell(out), write(a), false ; write(b)), told.
Unlike Edinburgh Prolog systems, telling/1 and seeing/1 do not return the filename of the current input/output but rather the stream identifier, to ensure the design pattern below works under all circumstances:106Filenames can be ambiguous and SWI-Prolog streams can refer to much more than just files.
..., telling(Old), tell(x), ..., told, tell(Old), ...,
The predicates tell/1
and see/1
first check for user
, the
pipe(command)
and a stream handle. Otherwise, if the
argument is an atom it is first compared to open streams associated to a
file with exactly the same name. If such a stream exists,
created using
tell/1
or see/1,
output (input) is switched to the open stream. Otherwise a file with the
specified name is opened.
The behaviour is compatible with Edinburgh Prolog. This is not without problems. Changing directory, non-file streams, and multiple names referring to the same file easily lead to unexpected behaviour. New code, especially when managing multiple I/O channels, should consider using the ISO I/O predicates defined in section 4.17.2.
user
is returned if the current input is the
stream user_input
to improve compatibility with traditional
Edinburgh I/O. See the introduction of
section 4.17.3 for details.user
is returned if the current output is the
stream user_output
to improve compatibility with
traditional Edinburgh I/O. See the introduction of
section 4.17.3 for details.user_input
.user_output
.