2015-02-24 3 views
2

Qu'est-ce que cela signifie de mettre la coupure (!) au tout début d'une clause?Couper le début d'une clause et la relation entre "couper", `!`, Et `fail`

p(X,Y) :- !, q(X), r(X,Y). 

Quelle est la différence entre ! et fail et comment sont-ils liés?

merci.
Je pense que pour fail, le prédicat va juste "échouer" lol ce qui est différent de ne pas revenir en arrière? voulez simplement être sûr :)

+2

Oui. 'fail' signifie * échec *. :) Cela signifie qu'il va revenir en arrière. Mais '!' Signifie * couper * et signifie qu'il ne reviendra pas en arrière de ce point dans la clause. Si votre exemple est un seul prédicat de clause, alors il ne fait rien car il n'y a rien à faire de backtrack de toute façon. Mais si vous aviez un autre 'p (X, Y): - s (X, Y).» * Après * celui que vous montrez, alors il ne serait jamais exercé en raison de la réduction de la clause précédente (puisque la clause préalable a seulement des variables pour les arguments et trouvera toujours une requête 'p (X, Y)' avant que la deuxième clause ne le fasse). – lurker

+2

Vous devriez obtenir un bon livre Prolog (comme * Programmation en Prolog * par Clocksin et Mellish pour le matériel d'introduction, ou * L'Art de Prolog * par Sterling et Shapiro) parce qu'ils expliquent ces concepts de manière approfondie. :) – lurker

+0

Ok merci beaucoup, j'avais effectivement téléchargé ça mais je n'ai pas eu l'occasion de le lire lol, mais je le lirai définitivement! –

Répondre

4

Habituellement, vous l'utilisez lorsque vous voulez vous assurer qu'il n'y a pas de retour arrière sur une certaine combinaison d'instanciations de variables. Pour afficher un code (emprunté un peu de the SWI-Prolog implementation.

read_lines(In, Ls) :- 
    read_line_to_codes(In, Codes), 
    read_lines_rest(Codes, In, Ls). 

read_lines_rest(end_of_file, _, []) :- !. 
read_lines_rest(Codes, In, [Codes|Rest]) :- 
    read_line_to_codes(In, New_codes), 
    read_lines_rest(New_codes, In, Rest). 

Maintenant, avec ces prédicats définis, vous pouvez lire un flux d'entrée (un fichier, par exemple) à une liste de lignes Nous utilisons read_line_to_codes/2 de library(readutil) . Il va unifier son second argument avec une liste de codes représentant une ligne, ou l'atome end_of_file à la fin de l'entrée.

dans la première clause de read_lines_read/3, nous utilisons l'unification dans la tête de la définition sous-jacente. nous " demande "que le premier argument doit être l'atome end_of_file si nous voulons que le prédicat soit même considéré. d d'entrée) cette clause réussit, l'autre solution possible dans la deuxième clause de la définition n'est pas prise en considération, et le prédicat réussit, fermant la liste dans le troisième argument.

Ici, il est utilisé:

?- open('shortcut.pl', read, In), read_lines(In, Ls), forall(member(L,Ls), format("~s~n", [L])). 
read_lines(In, Ls) :- 
    read_line_to_codes(In, Codes), 
    read_lines_rest(Codes, In, Ls). 

read_lines_rest(end_of_file, _, []) :- !. 
read_lines_rest(Codes, In, [Codes|Rest]) :- 
    read_line_to_codes(In, New_codes), 
    read_lines_rest(New_codes, In, Rest). 
% variable instantiations 

Vous remarquerez que le prédicat réussit exactement une fois. Essayez de supprimer la coupure dans le premier paragraphe pour voir ce qui se passe.

Comme pour le fail, oui, cela fait échouer le prédicat (échouer). À ce stade, s'il reste des points de choix, Prolog reviendra sur le plus récent.

+0

Merci pour l'explication, très clair maintenant !! –