2

Prolog (SWI-Prolog) で非常に単純な (おそらく) 問題が発生していますが、わかりません。

私が望むのは、ネストされたリストを複合項に交換できる再帰的述語を作成することです。

リスト表現で機能する代替アルゴリズムを使用していて、複合表現を出力として使用するため、これら 2 つの表現を交換したいと考えています。

だから私はしたい:

list_2_compound(List,Compound).

たとえば、次のように機能します

list_2_compound([seq, [seq, [if, p1, p2], p2], p1, p3], Compound).

Compound = seq(seq(if(p1, p2), p2), p1, p3)

したがって、通常は =.. 演算子を使用します。

Compound =.. [if, p1, p2] 
Compound = if(p1,p2)

しかし、ネストされたリストを横切る再帰的な方法で。

4

2 に答える 2

4

一見思ったよりも少しトリッキーです。

list_2_compound(L, T) :-
    var(T)
    ->  L = [F|Fs], maplist(list_2_compound, Fs, Ts), T =.. [F|Ts]
    ;   atomic(T)
    ->  L = T
    ;   L = [F|Fs], T =.. [F|Ts], maplist(list_2_compound, Fs, Ts).
list_2_compound(T, T).

(私の以前の投稿では、逆のケースであまりにも多くのネストされたリストが生成されました)。テスト:

1 ?- list_2_compound([seq, [seq, [if, p1, p2], p2], p1, p3], Compound).
Compound = seq(seq(if(p1, p2), p2), p1, p3) 
.

2 ?- list_2_compound(S, $Compound).
S = [seq, [seq, [if, p1, p2], p2], p1, p3] 
.

編集

@damianodamiano のコメントの後、バグがあることは明らかですが、そうではありません

同じ解を無限回

私たちが持っているので

?- aggregate(count,L^list_2_compound(L, seq(seq(if(p1, p2), p2), p1, p3)),N).
N = 45.

結局のところ、'catch all' 句が、上記の既に処理されたケースと無駄に重複しているだけです。しかし、混乱を避け、このスニペットの宣言型プロパティをより有効に活用するために、述語の名前を次のように変更しますlist_compound

list_compound(L, T) :-
    (   var(T)
    ->  L = [F|Fs], maplist(list_compound, Fs, Ts), T =.. [F|Ts]
    ;   atomic(T)
    ->  L = T
    ;   L = [F|Fs], T =.. [F|Ts], maplist(list_compound, Fs, Ts)
    ),
    !.
list_compound(T, T).

これで、決定論的な計算ができました。

?- list_compound(L, seq(seq(if(p1, p2), p2), p1, p3)).
L = [seq, [seq, [if, p1, p2], p2], p1, p3].

?- list_compound($L, C).
C = seq(seq(if(p1, p2), p2), p1, p3),
L = [seq, [seq, [if, p1, p2], p2], p1, p3].

したがって、これは@patta1986が2013年にコメントで説明したのと同じソリューションです...

于 2013-11-12T00:06:13.013 に答える