Solving constraints with string concatenations in Prolog

147 views Asked by At

Here, I tried to solve some simple string constraints in Prolog. While this problem seems to be straightforward, the main predicate still does not print the value of FinalString, which should be "hello world". Is it possible for Prolog to solve constraints that contain string concatenations, like this one?

:- set_prolog_flag(verbose,silent).
:- prompt(_, '').
:- use_module(library(readutil)).
main :-
    append("hello ", B, FinalString),
    append(A, "world", FinalString),
    append(A, B, FinalString),
    writeln(FinalString),
    true.
:-main.
1

There are 1 answers

1
false On BEST ANSWER

If you do experiments as a beginner, better stick to using the . In this manner you can rapidily identify the problem. Since you are most probably using SWI7 - like so:

?- append("hello ", B, FinalString),
   append(A, "world", FinalString),
   append(A, B, FinalString).
   false.

So if this is false, lets generalize it, by removing the rightmost goal:

?- append("hello ", B, FinalString),
   append(A, "world", FinalString).
   false.

Nah ...

?- append("hello ", B, FinalString).
   false.

The actual problem is that double quotes in SWI have now a non-conforming meaning. To get traditional behavior, call SWI with command line option --traditional and:

?- set_prolog_flag(double_quotes,chars).
   true.
?- append("hello ", B, FS).
   FS = [h,e,l,l,o,' '|B].

For more on this flag see this answer.

Now your original query produces a sensible answer:

?- append("hello ", B, FS),append(A, "world", FS),append(A, B, FS).
   B = [w,o,r,l,d], FS = [h,e,l,l,o,' ',w,o,r|...], A = [h,e,l,l,o,' ']
;  loops.

... or does it? It finds the answer you want, but at the same time, when being asked whether or not there is a further answer, it loops! Such problems can be easily detected when using the toplevel shell, but remain undetected with a script as yours. This loop is an inherent problem. There is no easy way out, because the fact that there is exactly one solution is caused by all three goals together.

If you really like to write it as a script, rather write it like so:

:- set_prolog_flag(double_quotes, chars).

main :-
    append("hello ", B, FinalString),
    append(A, "world", FinalString),
    append(A, B, FinalString),
    write(FinalString),
    nl,
    halt.

:- initialization(main).