PrologEZ
Data & computation · Lesson 26 of 43

Text & output

Atoms, strings, character lists, and printing with format/2.

Prolog has three common ways to hold text:

formexampletypical use
atomhello, 'Hello World'names, symbols, keys
string"hello"text you process or print
code/char list[0'h, 0'i], [h, i]analysing text character by character

Built-ins convert between them freely.

?- atom_length('Hello World', N)
?- atom_chars(hello, Chars)
?- atom_codes(hi, Codes)
?- atom_chars(Atom, [p, r, o, l, o, g])
?- upcase_atom(hello, Up)
?- atom_number('42', N), atom_number(A, 3.14)

Gluing and splitting

atom_concat/3 works in several directions; sub_atom/5 finds substrings; atomic_list_concat/3 joins and splits on a separator.

?- atom_concat(foo, bar, X)
?- atom_concat(X, Y, abc)
?- sub_atom(hello_world, Before, _, 0, world)
?- atomic_list_concat([a, b, c], '-', Joined)
?- atomic_list_concat(Parts, ',', 'x,y,z')

Strings

Double quotes create a string. The string_* predicates mirror the atom_* ones, and split_string/4 is the handy splitter:

?- string_concat("Hello, ", "world", S)
?- string_length("prolog", N)
?- split_string("a,b,,c", ",", "", Parts)
?- split_string("  padded  ", "", " ", [Trimmed])
?- string_chars(S, [h, i]), string_to_atom(S, A)
?- term_to_atom(foo(1, bar), A)
?- term_to_atom(T, 'point(3, 4)'), arg(1, T, X)

Printing

write/1 prints a term, print/1 and writeq/1 quote atoms when needed, nl/0 ends a line. format/2 is the powerful one, its directives:

directiveprints
~wany term, as write would
~qthe term, quoted so it could be read back
~aan atom
~dan integer (~2d inserts a decimal point)
~f, ~2fa float with the given digits
~sa string given as a list of codes
~t ~20|pad / align to a column
~nnewline
?- write('Hello World'), nl, writeq('Hello World'), nl, print([a, 'B', "c"])
?- format("~w is ~d years old~n", [alice, 30])
?- format("~a~t~12|~a~t~8+~a~n", [name, age, city]), format("~a~t~12|~d~t~8+~a~n", [ada, 36, london])
?- format("pi is about ~4f~n", [3.14159265])
?- format("~q and ~w~n", ['it\'s', 'it\'s'])
?- format(atom(A), "~w-~w", [x, y])

Turning text into a program's data

Because characters are just atoms of length one, you can recurse over text exactly as over lists:

count_vowels(Atom, N) :-
    atom_chars(Atom, Chars),
    include([C]>>member(C, [a, e, i, o, u]), Chars, Vowels),
    length(Vowels, N).
?- count_vowels(prolog, N)
?- count_vowels(programming, N)

Exercise: Palindromes

Write palindrome(Atom): true if the atom reads the same forwards and backwards (level, racecar). Single letters count. There must be exactly one answer.