Skip to content
Lesson 7 of 7

Step 1 of 4 · Reading · ~2 min

Learn

Unification, I/O, Arithmetic

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

Reading

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

The input must be a complete Prolog term followed by a period and a newline. That period is part of the data — a test whose input is 42. is feeding you the term 42, and without the period read_term/2 would sit waiting for the rest of it.

Writing

write(X)                          %% print without quoting atoms
write_term(X, [quoted(true)])     %% print so the result reads back
nl                                %% newline

writeln/1 does not exist in GNU Prolog, which is what grades this course — calling it raises existence_error(procedure, writeln/1) at run time, so the program compiles and then dies. SWI-Prolog has it; write write(X), nl instead and your code runs on both.

format/2 is the printf of Prolog, and the one to reach for whenever output mixes literal text with values:

format('~w is ~d years old~n', [ada, 36]).
%% ada is 36 years old

Format specs:

  • ~w — like write
  • ~q — quoted, read-back compatible
  • ~a — an atom
  • ~d — an integer (handing it a float is an error, not a rounding)
  • ~Nf — a float to N decimals: format('~2f', [3.14159]) prints 3.14
  • ~n — newline

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.

end_of_file is the atom read_term/2 hands back once the stream is exhausted, so it doubles as the loop's sentinel.

File I/O and streams

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).

current_input/1 and current_output/1 name the default streams; set_input/1 and set_output/1 change them. Graded problems here read stdin and write stdout, so you rarely need any of it.

The count-then-read pattern

:- 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).

Read a count, then read that many terms, then do something with them. Note that sum_list/2 is called here, not defined — it is a GNU Prolog built-in, and writing your own clause for it is a fatal compile error.

For grammar-shaped parsing Prolog has DCG notation, which the Intermediate course covers.

Discussion

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

Sign in to post a comment or reply.

Loading…