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:
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-[])
.
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 dcg à 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
.
@ p.s.w.g: Pourquoi avez-vous voté pour fermer cette page? – false
'' -'' 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). –
Vous avez totalement raison - malheureusement, il ne me laisse pas enlever le drapeau. J'ai supprimé mon commentaire, cependant. –