Working with strings in Prolog
Strings in Prolog can be quite confusing if you come from another language. In this short article I will illustrate how they work, mainly by showing different examples and by creating a term that checks if a string is contained within another string.
First off, strings in Prolog are written in single quotes. Terms written in double quotes are immediately converted to a list of character codes. Therefore, strings can be handed directly to write. Strings are also atoms.
?- 'bergen' = L. L = bergen. ?- "bergen" = L. L = [98, 101, 114, 103, 101, 110]. ?- atom('bergen'). true. ?- is_list("bergen"). true. ?- write('sdf'). sdf true. ?- write("sdf"). [115, 100, 102] true. ?- writef("%s", ["sdf"]). sdf true.
Since strings in Prolog are atoms, they naturally cannot be manipulated. So for certain tasks they need to be converted to char lists. This can be done with name. So to print the first character of a string you'll have to convert it to a char list first.
?- name('bergen', CharList), nth0(0, CharList, FirstChar), put(FirstChar). b CharList = [98, 101, 114, 103, 101, 110], FirstChar = 98.
We now know enough to create our term, contains/2. For illustration, we will make it work for both strings and char lists, by converting to a char list when needed. It will succeed if A is contained within B. We'll need a utility term for this as well. Note that I am using SWI-Prolog, so I am utilizing built in terms that might not be available elsewhere. of this article, but they should be decipherable if you have written recursive terms in Prolog. The full program as well as an example that generates all possible substrings contained within A follows below.
sublist(S, L) :- append(_, L2, L), append(S, _, L2). contains(A, B) :- atom(A), atom(B), name(A, AA), name(B, BB), contains(AA, BB). contains(A, B) :- atom(A), name(A, AA), contains(AA, B). %% The empty list is removed mainly for nicer output in the following example. contains(A, B) :- sublist(B, A), B \= []. ?- forall( contains('bergen', X) , writef("%s\n", [X]) ). b be ber berg berge bergen e er erg erge ergen r rg rge rgen g ge gen e en n true.