2010-05-23 5 views
1

Pourquoi Prolog correspond (X, Xs) à un tuple contenant plus d'éléments? Un exemple:Tuples correspondants dans Prolog

test2((X, Xs)) :- write(X), nl, test2(Xs).          
test2((X)) :- write(X), nl.             

test :-                  
     read(W),                
     test2(W). 

?- test. 
|: a, b(c), d(e(f)), g. 
a 
b(c) 
d(e(f)) 
g 
yes 

En fait, c'est ce que je veux atteindre, mais il semble suspect. Existe-t-il un autre moyen de traiter une conjonction de termes sous forme de liste dans Prolog?

Répondre

2

Tuple terme construction avec l'opérateur ,/2 est généralement droit associatif en Prolog (généralement appelée une séquence ), de sorte que votre entrée a, b(c), d(e(f)), g pourrait bien effectivement être le terme (a, (b(c), (d(e(f)), g))). Ceci est démontré par le fait que votre prédicat test2/1 imprimé ce qui est indiqué dans votre question, où le premier appel de la première clause de test2/1, X en correspondance a et Xs en correspondance (b(c), (d(e(f)), g)), puis sur la deuxième invocation X assortie b(c) et Xs assorti (d(e(f)), g) , etc.

Si vous voulez vraiment faire face à une liste des termes interprétés comme une conjonction, vous auriez pu utiliser les éléments suivants:

test2([X|Xs]) :- write(X), nl, test2(Xs).          
test2([]). 

... sur l'entrée [a, b(c), d(e(f)), g]. La structure de liste ici est généralement interprétée un peu différemment des tuples construits avec ,/2 (comme, au moins dans SWI-PROLOG, de telles structures sont du sucre syntaxique pour traiter des termes construits avec ./2 de la même manière que vous construiriez des séquences ou des tuples termes avec ,/2). De cette façon, vous obtenez les avantages de la prise en charge des termes de liste, si vous pouvez autoriser les termes de liste à interprétés comme des conjonctions dans votre code. Une autre alternative consiste à déclarer et utiliser votre propre (peut-être opérateur infixe) pour la conjonction, comme &/2, que vous pouvez déclarer:

:- op(500, yfx, &). % conjunction constructor 

Vous pouvez ensuite construire votre conjoint comme a & b(c) & d(e(f)) & g et traiter de manière appropriée de là, sachant exactement ce que vous entendez par &/2 - conjonction.Voir la page de manuel pour op/3 dans SWI-PROLOG pour plus de détails - si vous n'utilisez pas SWI, je présume qu'il devrait y avoir un prédicat semblable dans n'importe quelle implémentation PROLOG que vous utilisez - si ça vaut le coup: -)

EDIT: pour convertir un terme tuple construit à l'aide ,/2 à une liste, vous pouvez utiliser quelque chose comme ce qui suit:

conjunct_to_list((A,B), L) :- 
    !, 
    conjunct_to_list(A, L0), 
    conjunct_to_list(B, L1), 
    append(L0, L1, L). 
conjunct_to_list(A, [A]). 
+0

Vos réponses post pourquoi est-ce travail de construction (,/2 opérateur) mais je ne sais toujours pas si c'est la bonne façon de gérer cette entrée. Le problème est que je ne peux pas traiter une liste de termes parce que je reçois le tuple en entrée. Peut-être qu'il y a un moyen de convertir un tuple en liste? Pourtant, je pourrais faire quelque chose comme ça: convertir ((X, Xs), [X | R]): - convertir (Xs, R). convertir (X, [X]). – milosz

+0

J'ai ajouté 'conjunct_to_list/2' qui devrait aider à convertir un terme construit avec',/2' en une liste ('./2'). – sharky

+0

Vous auriez pu écrire le premier comme ceci 'conjunct_to_list ((A, B), [A | T]): -!, Conjunct_to_list ((B), T) .'. Mais n'y a-t-il pas moyen de le faire sans '!'? – ohcibi

0

Hmm ... a, b(c), d(e(f)), g signifie a et (b(c) et (d(e(f)) et g)), liste bien [1,2,3] est juste un [1 | [2 | [3 | []]]]. C'est à dire. Si vous convertissez cette conjonction en une liste, vous obtiendrez le même test2([X|Xs]):-..., mais la différence est que la conjonction porte des informations sur la façon dont ces deux objectifs sont combinés (il peut également y avoir une disjonction (X; Xs)). Et vous pouvez construire une autre hiérarchie de conjonctions par (a, b(c)), (d(e(f)), g)

Vous travaillez avec des types récursifs simples. Dans d'autres langages, les listes sont aussi des types récursifs, mais ils prétendent souvent être des tableaux (big-big tuples avec une bonne indexation).

Probablement vous devez utiliser:

test2((X, Y)):- test2(X), nl, test2(Y). 
test2((X; Y)). % TODO: handle disjunction 
test2(X) :- write(X), nl.