2013-03-16 2 views
9

J'ai lu la réponse à this question,Que signifie le symbole "-" dans Prolog lorsqu'il s'agit de listes?

p(X) :- read(A), q(A,X-[]). 

q(end,X-X) :- !.  
q(A,[A|X]-Y) :- read(B), q(B,X-Y). 

Le code ci-dessus utilise la syntaxe Liste Liste. Je comprends un peu ce qui se passe, mais je veux savoir exactement ce que le symbole "/" fait ici. En outre, est-ce spécifique à SWI?

+0

@ p.s.w.g: Pourquoi avez-vous voté pour fermer cette page? – false

+1

'' -'' n'est pas un prédicat, c'est un "foncteur" - nom d'une structure composée. Par exemple. dans 'f (1,2)', 'f' est un foncteur d'un terme composé avec deux arguments. (Si vous effectuez une recherche, faites une recherche pour "foncteur Prolog", juste "functor" vous montrera une tonne de choses sans rapport). –

+0

Vous avez totalement raison - malheureusement, il ne me laisse pas enlever le drapeau. J'ai supprimé mon commentaire, cependant. –

Répondre

6

Le (-)/2 pour représenter listes différence est une convention plutôt rare. Dans les livres plus anciens, un autre opérateur (\)/2 a également été utilisé.

Beaucoup préfèrent utiliser deux arguments distincts à la place. Il y a plusieurs avantages par rapport à l'aide d'un opérateur:

  1. Le prédicat ne peut accidentellement être utilisé avec une variable non pour l'argument. Pensez à appeler q(A, X) à la place de q(A, X-[]).

  2. L'exécution est encore un peu plus efficace lorsque vous utilisez deux arguments. De nombreux systèmes, comme SWI, doivent créer chaque structure (-)/2 dynamiquement.

Néanmoins, il y a aussi une autre façon d'utiliser des listes de différence, ce qui est souvent moins sujette aux erreurs: Vous pouvez utiliser un à cet effet. En fait, il y a deux erreurs dans le programme, dont l'une est causée par la manière dont la liste des différences est gérée. L'autre erreur est que le programme ne gère pas la fin du fichier. Il serait préférable d'utiliser end_of_file à la place de end. Mais c'est une chose superficielle que vous auriez trouvée tôt ou tard.

L'autre erreur plus subtile est due à l'interaction entre les listes de différences et la coupe. Je ne suis pas un grand fan des coupes, mais regardons cette règle. Une coupe coupe après que tout a été exécuté sur son côté gauche.

q(end_of_file,X-X) :- !. 

Le premier argument est l'atome end_of_file. Puisque nous utilisons q/2 seulement avec le résultat de read/1 comme premier argument, ceci peut seulement être une comparaison. Nous sommes donc à la fin du fichier (ou du flux). Ensuite, cependant, il y a d'autres choses qui doivent tenir. Et seulement si ceux-ci réussissent aussi, la coupure sera-t-elle exécutée: Le deuxième argument doit être un (-)/2 (ok, dans tous les endroits il y a un moins à sa place). Et puis: Les deux arguments de (-)/2 doivent être identiques (doit unifier). Pourquoi? Nous sommes à la fin du fichier, mais si ces arguments ne s'unifient pas, l'autre règle sera essayée.

Quand cela se produit-il?Voici ce cas méchant:

p([X,Y,Z]). 

Et il suffit d'entrer une seule constante, dire my_constant. puis appuyez sur Cntrl-d ou Cntrl + z. Que devrait faire p/1 dans un tel cas? Idéalement, il échouerait après avoir terminé l'entrée. Cependant, il faudra attendre d'autres commentaires.

La raison en est le placement inapproprié de la coupe. Nous disons que p/1 n'est pas fixe. C'est une erreur courante dans les programmes Prolog. Je ne peux que recommander de réduire l'utilisation des coupes et l'adoption des DCG. Avec DCG, cela ne peut se produire:

p2(X) :- read(A), phrase(q2(A),X). 

q2(end_of_file) --> !. 
q2(A) --> [A], {read(B)}, q2(B). 

Avec DCG, la coupe est exécutée quel que soit l'argument de p/1.

+0

'q (fin_de_fichier, Z): -!, Z = X-X. q (fin, Z): -!, Z = X-X.'. Je dis juste. Je pense que "Clause et Effet" utilise le foncteur '' -'', IIRC. –

+0

@WillNess: Vous connaissez une bibliothèque concrète dans un système Prolog qui utilise cette convention? – false

+0

non, je n'ai rien dit de tel. "Cause et effet" est un livre de 80 s, je pense. –