2016-04-15 16 views
4

append/3は非常に強力な述語です。 SWI-Prologの文字列の場合と同じように動作する述語が必要だとします。SWI-Prologの可逆述語と文字列

私が見る最も簡単なアプローチは、​​でリストに変換してからappend/3を適用し、次に​​を使用します。このアプローチの大きな問題は、両方の変数が統合されていない場合、​​が機能しないことです。ここで

は私が必要なとき​​を適用するために統一されている文字列をチェックする、思い付いた非常に醜いソリューションです:

?- 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. 

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). 

これは、次のような場合のために正しい結果が得られ

これより簡単にする方法はありませんか?私はリストと同じように文字列を扱う述語をたくさん作成したいと考えています。私は明らかにそれらのすべてのためにappend/3のために行ったことを書く必要はありません。しかし、コード・ストリングで作業したくないのは、通常のリストを操作しているのか実際にストリングを操作しているのかを知る方法がないからです。

+1

最も簡単な方法は、文字列を直接使用しないことです。代わりに['chars'を使う](http://stackoverflow.com/a/36645725/772868)。 – false

+1

'append_strings(Xs、Ys、Zs)'の定義が失敗します。むしろインスタンス化エラーを生成するはずです。 – false

+0

@falseしかし、私はリストと文字列を区別することはできません。リストを転置する述語転置が必要だとしますが、文字列に対しては改行に従って転置します。文字のリストでは、文字列で作業しているかどうかを知る方法がありません。 – Fatalize

答えて

3

string_concat/3を使用してください。 ISO atom_concat/3と同様、( - 、 - 、+)を含む多くのモードで使用できます。

1

いくつかの時間前similar questionがあった、私は私の提案が表示されます、あなたが興味を持っている場合、私は

のようなものを取得するには、構文の詳細を隠すためにオペレータを追加することができます

:- meta_predicate when_(0). 
when_(P) :- 
    strip_module(P,_,Q), Q =.. [_|As], 
    or_list(As, Exp), % hurry debugging :-) display(Exp), 
    when(Exp, P). 

or_list([A], ground(A)) :- !. 
or_list([A|As], (ground(A);Exp)) :- or_list(As, Exp). 

append_strings(S1, S2, S3) :- 
    maplist(when_, [string_codes(S1, A), string_codes(S2, B), append(A,B,C), string_codes(S3, C)]). 

を改訂

append_strings(S1, S2, S3) -:- 
    string_codes(S1, A), string_codes(S2, B), append(A,B,C), string_codes(S3, C). 
1

これは、よりコンパクトな定義です:

append_strings(S1, S2, S3):- 
    append_strings1(S1, L1, [1]-[], N1), 
    append_strings1(S2, L2, [1|N1]-N1, N2), 
    append_strings1(S3, L3, [1,1|N2]-N2, N3), 
    (N3\=[_,_|_] ->instantiation_error(append_strings/3); true), 
    append(L1, L2, L3), 
    (ground(S1)->true;string_codes(S1, L1)), 
    (ground(S2)->true;string_codes(S2, L2)), 
    (ground(S3)->true;string_codes(S3, L3)). 

append_strings1(S, L, G-NG, N):- 
    (ground(S) -> (string_codes(S, L), N=G) ; N=NG). 

それを確認それぞれの引数がグラウンドであり、コードに変換しようとしているかどうかをチェックし、3番目の引数がグラウンドであるか、それとも2つであるかをチェックし、条件が満たされない場合はインスタンス化エラーをスローします。

追加の後、それは地面ではない文字列引数に変換されます。

4

述語はリストに作用しているので、DCGを使用するのは魅力的です。最初のは、プロローグ内の文字列が実際に文字コードのリストであることを確認してみましょう:もちろん

?- X="test". 
X = [116,101,115,116] 

、これは非常に読みやすいではないので、の文字inteadそのコードの自分自身を見てみましょう:良いでしょう

?- set_prolog_flag(double_quotes,chars). 
yes 
    ?- X="test". 
X = [t,e,s,t] 

を。述語が記述すべき関係について考えると、私はlist_list_appended/3のようなわかりやすい名前を選ぶ。この述語は、一つの目標を持っています

list_list_appended(L1,L2,L3) :- 
    phrase(list_list(L1,L2),L3). % L3 is L1+L2 

list([]) -->      % if the list is empty ... 
    [].       % ... there's nothing in the list 
list([X|Xs]) -->     % if there's a head element ... 
    [X],       % ... it's in the list 
    list(Xs).      % the tail is also a list 

list_list(L1,L2) -->    % the list consists of ... 
    list(L1),      % ... L1 followed by ... 
    list(L2).      % L2 

あなたの例クエリ:DCG-ルールは、// 2は、別のDCGを使用する、のは実際にリストを書くために、//それはリスト2を呼びましょうlist_listのは、それを呼びましょう

あなたはまた、所望の形態で出力を得るために set_prolog_flag(double_quotes,chars).と組み合わせて this libraryを使用することができSWIユーザーとして
?- list_list_appended("test","auie","testauie"). 
yes 
    ?- list_list_appended(L1,"auie","testauie"). 
L1 = [t,e,s,t] ? ; 
no 
    ?- list_list_appended("test",L2,"testauie"). 
L2 = [a,u,i,e] ? ; 
no 
    ?- list_list_appended("test","auie",L3). 
L3 = [t,e,s,t,a,u,i,e] 
    ?- list_list_appended(L1,L2,"testauie"). 
L1 = [], 
L2 = [t,e,s,t,a,u,i,e] ? ; 
L1 = [t], 
L2 = [e,s,t,a,u,i,e] ? ; 
L1 = [t,e], 
L2 = [s,t,a,u,i,e] ? ; 
L1 = [t,e,s], 
L2 = [t,a,u,i,e] ? ; 
L1 = [t,e,s,t], 
L2 = [a,u,i,e] ? ; 
L1 = [t,e,s,t,a], 
L2 = [u,i,e] ? ; 
L1 = [t,e,s,t,a,u], 
L2 = [i,e] ? ; 
L1 = [t,e,s,t,a,u,i], 
L2 = [e] ? ; 
L1 = [t,e,s,t,a,u,i,e], 
L2 = [] ? ; 
no 

。詳細はthis answerを参照してください。