append/3
est un prédicat très puissant. Supposons que je veuille un prédicat qui fonctionne de la même manière mais pour les chaînes de SWI-Prolog.Prédicats et chaînes réversibles dans SWI-Prolog
L'approche la plus simple que je vois est de transformer ces chaînes en listes avec string_codes/2
, puis d'appliquer append/3
, puis d'utiliser string_codes/2
retour. Le gros problème de cette approche est que string_codes/2
ne fonctionne pas si les deux variables ne sont pas unifiées.
Voici une solution extrêmement laide je suis venu avec, qui vérifie que les chaînes sont unifiés à appliquer string_codes/2
en cas de besoin:
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).
Cela donne des résultats corrects pour les cas suivants:
?- 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.
N'y a-t-il vraiment aucun moyen de simplifier les choses? Supposons que je veux faire un tas de prédicats qui fonctionnent avec des chaînes comme ils le feraient avec des listes: je ne veux évidemment pas avoir à écrire ce que j'ai fait pour append/3
pour chacun d'entre eux. Mais je ne veux pas non plus travailler avec des chaînes de code parce que je n'ai aucun moyen de savoir si je manipule une liste normale ou vraiment une chaîne.
La méthode la plus simple consiste à ne pas utiliser les chaînes directement. Au lieu de cela, utilisez [chars] (http://stackoverflow.com/a/36645725/772868). – false
Votre définition échoue pour 'append_strings (Xs, Ys, Zs)'. Il devrait plutôt produire une erreur d'instanciation. – false
@false Mais alors je ne peux pas faire la différence entre une liste et une chaîne. Supposons que je souhaite une transposition de prédicat qui transpose une liste, mais pour une chaîne, elle transpose selon les sauts de ligne. Avec une liste de caractères, je n'ai aucun moyen de savoir si je travaille avec une chaîne ou non. – Fatalize