append/3
is a very powerful predicate. Suppose I want a predicate that works the same way but for SWI-Prolog's strings.
The easiest approach I see is to transform those strings into lists with string_codes/2
, then apply append/3
, then use string_codes/2
back. The big problem with this approach is that string_codes/2
does not work if both variables are not unified.
Here is an extremely ugly solution I came up with, which checks which strings are unified to apply string_codes/2
when needed:
append_strings(S1, S2, S3) :-
nonvar(S1),
nonvar(S2),!,
string_codes(S1, A),
string_codes(S2, B),
append(A,B,C),
string_codes(S3, C).
append_strings(S1, S2, S3) :-
nonvar(S1),
nonvar(S3),!,
string_codes(S1, A),
string_codes(S3, C),
append(A,B,C),
string_codes(S2, B).
append_strings(S1, S2, S3) :-
nonvar(S2),
nonvar(S3),!,
string_codes(S2, B),
string_codes(S3, C),
append(A,B,C),
string_codes(S1, A).
append_strings(S1, S2, S3) :-
nonvar(S3),
string_codes(S3, C),
append(A,B,C),
string_codes(S1, A),
string_codes(S2, B).
This yields the correct results for the following cases:
?- append_strings("test","auie","testauie").
true.
?- append_strings("test",A,"testauie").
A = "auie".
?- append_strings(A,"auie","testauie").
A = "test" ;
false.
?- append_strings(A,B,"testauie").
A = "",
B = "testauie" ;
A = "t",
B = "estauie" ;
A = "te",
B = "stauie" ;
A = "tes",
B = "tauie" ;
A = "test",
B = "auie" ;
A = "testa",
B = "uie" ;
A = "testau",
B = "ie" ;
A = "testaui",
B = "e" ;
A = "testauie",
B = "" ;
false.
Is there really no way to make things simpler than this? Suppose I want to make a whole bunch of predicates that work with strings just like they would with lists: I obviously don't want to have to write what I did for append/3
for all of them. But I also don't want to work with code strings because then I have no way of knowing whether I am manipulating a normal list or really a string.
chars
. – falseappend_strings(Xs,Ys,Zs)
. It should rather produce an instantiation error. – false