Zapisanie do PROLOGU: set_intersec([], []).
//W Prologu nie można zwracać true ani false, ale procedura może się powieść, albo nie. I to wykorzystujemy:
// member zakończyło się powodzeniem
set_intersec([X|R], Set2, [X|Intl]) :- member(X, Set2), set_intersec(R, Set2, Intl).
// member zakończyło się niepowodzeniem
set_intersec([X|R], Set2, Intl) :- not member(X, Set2), setintersec(R.Set2.lntl). (?!)
W sumie negację można sobie samemu napisać, nie patrząc na procedury wbudowane.
Jeżeli wywołujemy setjntersec po prawej stronie jakiejś reguły, to wiadomo, że trzecia reguła nigdy się nie wykona przy pierwszym podejściu. Przy nawrocie, interpreter wybierze pozostałą możliwość i przy nawrocie wejdzie w trzecią możliwość.
Jeżeli wyrzucimy z prawej strony 3 reguły "not member...", otrzymamy niedeterminizm niezamierzony, robi się błąd. Konieczny jest pewien mechanizm siłowy, który umożliwia pisanie czegoś w stylu 'else'. Warunek już raz został spełniony i w drugą gałąź nie trzeba wchodzić.
Taki mechanizm istnieje.
insert(X, [Y|Rest], [Y|Restl]) :- X>Y, insert(X, Rest, Restl). // Przesuwanie X po liście do coraz wyższych elementów, aż w końcu znalezienie odpowiedniego miejsca i...
insert(X, [Y|Rest], [X,Y|Rest]) :- X =< Y. //... wstawienie
Żeby nie sprawdzać dla drugiej reguły warunku, który już raz został sprawdzony, przy możliwości nawrotu w wywołaniu po prawej stronie, stosujemy ODCIĘCIE. Oznaczone przez "!".
insert(X, [Y|Rest], [Y|Restl]) :-X>Y, !, insert (X, Rest, Restl). insert(X, List, [X|List]).
Zinterpretowanie odcięcia powoduje wymazanie z pamięci interpretera wszystkich punktów, które wystąpiły przed odcięciem w kontekście przetwarzania procedury.
P' :-Q, !, R.
P" :- S, T.
PO x
P"
P'
Q1,R1
x
not_member(X, L) :- member(X,L). //jeżeli member zakończy się nie powodzeniem