Skip to content
Input and Output
step 1/4

Reading — step 1 of 4

Learn

~2 min readUnification, I/O, Arithmetic

Prolog's I/O is built around terms. read_term/2 parses a term; write/1 prints one.

Reading

?- read_term(X, []).
|: foo(bar, 42).         %% user types this
X = foo(bar, 42).

The input must be a complete Prolog term followed by . and a newline.

Writing

write(X)             %% pretty-print without quotes around atoms
writeln(X)            %% write + nl
write_term(X, [quoted(true)])    %% with proper quoting

format/2 — like printf:

format('~w is ~d years old~n', [Name, Age]).

Format specs:

  • ~w — same as write
  • ~q — quoted (read-back compatible)
  • ~a — atom
  • ~d — integer
  • ~f — float
  • ~e — scientific notation
  • ~n — newline
  • ~p — print (custom)

Reading lines as strings

GNU Prolog and SWI-Prolog differ. SWI-Prolog has read_string/5:

read_string(user_input, _, _, _, Line).

GNU Prolog uses get_char/1 in a loop or specific string predicates.

Reading multiple terms

read_all(End, Acc, Result) :-
    read_term(T, []),
    ( T == End ->
        reverse(Acc, Result)
    ; read_all(End, [T|Acc], Result)
    ).

main :-
    read_all(end_of_file, [], Terms),
    write(Terms), nl.

File I/O

%% Read all from a file
read_file(File, Terms) :-
    open(File, read, Stream),
    read_terms(Stream, Terms),
    close(Stream).

read_terms(Stream, []) :-
    peek_char(Stream, end_of_file), !.
read_terms(Stream, [T|Rest]) :-
    read(Stream, T),
    read_terms(Stream, Rest).

Streams

  • current_input/1, current_output/1 — current default streams
  • set_input/1, set_output/1 — change them
  • with_output_to(StringSink, Goal) — redirect output

DCG (Definite Clause Grammars) — preview

For sophisticated text parsing, Prolog has DCG syntax — covered in Intermediate. It lets you write parsers that look like grammar rules.

Practical I/O patterns in Judge0

For problems that read a list of values:

:- initialization(main).

main :-
    read_term(N, []),
    read_n(N, Vals),
    sum_list(Vals, S),
    write(S), nl.

read_n(0, []) :- !.
read_n(K, [V|Rest]) :-
    K > 0,
    read_term(V, []),
    K1 is K - 1,
    read_n(K1, Rest).

This pattern is reusable — read a count, then read N terms, do something.

Discussion

Ask a question, share an insight, or help someone who’s stuck.

Sign in to post a comment or reply.

Loading…