user3053452
user3053452

Reputation: 675

Prolog - split word into separate letters

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

Answers (2)

lurker
lurker

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

damianodamiano
damianodamiano

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

Related Questions