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— likewrite~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])prints3.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…