title: Reversible predicates and Strings in SWI-Prolog
body: <p><code>append/3</code> is a very powerful predicate. Suppose I want a predicate that works the same way but for SWI-Prolog's strings.</p>
  
  <p>The easiest approach I see is to transform those strings into lists with <code>string_codes/2</code>, then apply <code>append/3</code>, then use <code>string_codes/2</code> back. The big problem with this approach is that <code>string_codes/2</code> does not work if both variables are not unified.</p>
  
  <p>Here is an extremely ugly solution I came up with, which checks which strings are unified to apply <code>string_codes/2</code> when needed:</p>
  
  <pre><code>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).
  </code></pre>
  
  <p>This yields the correct results for the following cases:</p>
  
  <pre><code>?- 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.
  </code></pre>
  
  <p>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 <code>append/3</code> 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.</p>