Reputation: 675
Follow up to this question. How could I split the word into letters without using lists or built-in predicate atom_chars/2.
Something along the lines of split_word(Word, Letter, Rest).
Where Letter would be 1st letter of the word.
I'm having difficulties splitting string and I don't know how to utilize ''
as "splitter". To get an inspiration I tried checking source code of atom_chars/2
with predicate_property(atom_char(_,_), P).
where I got to the source, but in the file I didn't find anything useful.
Help appreciated.
Upvotes: 0
Views: 2027
Reputation: 58244
By "splitting a string into atoms" I assume you mean more specifically "splitting a string into a list of characters".
First, we need to distinguish strings versus *atoms. In Prolog, a string as denoted with double quotes is normally a list of character codes, whereas an atom as denoted with single quotes, or a name starting with a lower case letter, is a symbol. See What is the difference between ' and " in Prolog. Here's what it looks like in GNU Prolog:
| ?- X = "abc". % A string of characters
X = [97,98,99]
yes
| ?- X = 'abc'. % An atom
X = abc
yes
| ?- X = abc. % An atom
X = abc
yes
| ?- X = 'Abc'. % An atom
X = 'Abc'
yes
| ?-
So, if you want to get the head and rest of a list of character codes from a string, it's as simple as unifying them:
| ?- "abcd" = [H | T].
H = 97
T = [98,99,100]
yes
| ?-
On the other hand, if you want to do this with an atom, then you need first to convert the atom to character codes using atom_chars/2
:
| ?- atom_chars(abc, [H|T]).
H = a
T = [b,c]
yes
| ?-
In SWI Prolog, they've allowed the use of double quotes to represent an integral string without it representing a list of character codes. It is not, though, the same as an atom. See Why has the representation of double quoted text changed?. Here are some queries in SWI Prolog:
1 ?- "abc" = 'abc'.
false.
2 ?- X = "abc".
X = "abc".
3 ?- "abc" = [H|T].
false.
4 ?- atom_chars("abc", [H|T]).
H = a,
T = [b, c].
5 ?- atom_chars(abc, [H|T]).
H = a,
T = [b, c].
Oddly, "abc"
is not the same as the atom abc
(as seen by the failing unification), but atom_chars/2
treats "abc"
the same as it would the atom, abc
.
Prolog has flags that affect its behavior. In SWI Prolog specifically, there is the double_quotes
flag, whose value can be modified so that the double quote representation behaves in the traditional Prolog sense, as shown in the GNU Prolog example above.
Back to the problem at hand, atom processing predicates are fairly fundamental to Prolog, so it's good to know the basic ones by heart if you need to do atom processing in a closed-book exam.
Upvotes: 1
Reputation: 2662
As far as i understand, you don't want to use atom_chars/2
but it's ok to use other built-in predicates. You can use sub_string/5
and string_length/2
to solve the problem in this way in SWI Prolog:
split(_,0).
split(S,Len):-
Len > 0,
Len1 is Len-1,
sub_string(S,0,1,_,Sub), %get the first letter
writeln(Sub),
sub_string(S,1,Len1,_,Sub1), %get the rest of the string
split(Sub1,Len1).
solve(S):-
string_length(S,Len),
split(S,Len).
?- solve("abcd").
a
b
c
b
true
Upvotes: 1