(-)/2
reprezentuje różnicę wymienia jest raczej rzadkością konwencji. W starszych książkach był również używany inny operator (\)/2
.
Wielu woli używać zamiast tego dwóch oddzielnych argumentów. Istnieje kilka korzyści w porównaniu z korzystaniem z operatora:
Predykatu nie można przypadkowo użyć z niepotwierdzoną zmienną dla argumentu. Pomyśl o wywołaniu q(A, X)
zamiast q(A, X-[])
.
Wykonanie jest nawet trochę bardziej wydajne, gdy używa się dwóch argumentów. Wiele systemów, takich jak SWI, musi dynamicznie tworzyć każdą strukturę (-)/2
.
Niemniej jednak, istnieje również inny sposób na wykorzystanie list różnica, która jest często mniej podatne na błędy: Można użyć dcg do tego celu.
W rzeczywistości są dwa błędy w programie, z których jeden jest spowodowany sposobem obsługi listy różnic. Innym błędem jest to, że program nie obsługuje końca pliku. Byłoby lepiej użyć end_of_file
zamiast end
. Ale to jest powierzchowne, co wcześniej czy później byś odkrył.
Drugi, bardziej subtelny błąd wynika z interakcji między listami różnic i cięciem. Nie jestem wielkim fanem cięć, ale spójrzmy na tę zasadę. Cięcie cięć po tym, jak wszystko na lewą stronę zostało wykonane.
q(end_of_file,X-X) :- !.
Pierwszy argument to atom end_of_file
. Ponieważ używamy q/2
tylko z wynikiem read/1
jako pierwszego argumentu, może to być tylko porównanie. Jesteśmy na końcu pliku (lub strumienia). Następnie jednak są dalsze rzeczy, które muszą się utrzymywać. I tylko wtedy, gdy ci się powiodą, rozcięcie zostanie wykonane: Drugi argument musi być (-)/2
(no dobrze, we wszystkich miejscach na jego miejscu znajduje się minus). A następnie: dwa argumenty (-)/2
muszą być takie same (należy ujednolicić). Czemu? Jesteśmy na końcu pliku, ale jeśli te argumenty nie zostaną zunifikowane, druga zasada zostanie wypróbowana.
Kiedy to się dzieje?Tutaj jest taki paskudny przypadek:
p([X,Y,Z]).
I wystarczy wpisać jedną stałą, powiedzmy my_constant.
a następnie naciśnij cntrl-d lub cntrl + z. Co powinien zrobić w takim przypadku p/1
? W idealnej sytuacji zakończyłoby się to niepowodzeniem po zakończeniu wprowadzania danych. Jednak będzie czekać na dalsze wprowadzanie.
Powodem jest niewłaściwe umieszczenie cięcia. Mówimy, że p/1
nie jest niezłomny. Jest to częsty błąd w programach Prolog. Mogę tylko zalecić ograniczenie stosowania cięć i przyjęcie DCG. Z DCGs, to nie może się zdarzyć:
p2(X) :- read(A), phrase(q2(A),X).
q2(end_of_file) --> !.
q2(A) --> [A], {read(B)}, q2(B).
z DCGs, cięcie jest wykonywane niezależnie od argumentu p/1
.
@ p.s.w.g: Dlaczego zagłosowałeś, aby to zamknąć? – false
'' -'' tutaj nie jest predykatem, jest "funktorem" - nazwą złożonej struktury. Na przykład. w 'f (1,2)', 'f' jest funktorem złożonego terminu z dwoma argumentami. (jeśli szukasz, szukaj "Funktora Prologa", po prostu "funktor" pokaże ci mnóstwo niespokrewnionych rzeczy). –
Masz całkowitą rację - niestety, nie pozwolę mi usunąć flagi. Skasowałem jednak mój komentarz. –