once/1
можно определить как
once(Goal) :- Goal, !.
Я пытаюсь понять разницу между этими двумя примерами, которые появились в обсуждении в документации SWI Prolog:
Обратите внимание, что это совершенно не то же самое, что использовать «вырезать»: [...]
Один раз подтвердите первое предложение:
foo(A,B) :- once(member(A-B,[a-1,b-2,c-3,a-4])). foo(A,B) :- member(A-B,[d-5,e-6,a-7,f-8]).
Затем:
?- foo(a,B). B = 1 ; B = 7 ; false.
Но если вырезать в конце первого предложения:
foo(A,B) :- member(A-B,[a-1,b-2,c-3,a-4]),!. foo(A,B) :- member(A-B,[d-5,e-6,a-7,f-8]).
Вы получаете:
?- foo(a,B). B = 1.
Я не слежу за сферой применения !
. Я бы предположил, что эти два одинаковы, т. е. разрез распространяется из once
, но, похоже, это не так. Может ли кто-нибудь объяснить, как работает сокращение в примере once
?
@brebs, кажется, он не отвечает
Да, «логический капитан» плавал в открытом море. Многие их комментарии на веб-сайте документации SWI-Prolog очень сбивают с толку. Не обращайте внимания на все, что вы видите в комментариях к документации, если их написал логический капитан. Я не хочу обсуждать примеры, которые вы оттуда скопировали, потому что из них сложно вынести что-то полезное.
Cut не распространяется за пределы Once/1. Фактически, определение Once/1:
once(Goal) :-
call(Goal), !.
именно так, чтобы !/0 не вылезал.
Разрез в этом определении один раз/1 работает следующим образом: всякий раз, когда call(Goal)
завершается успешно в первый раз (до этого он мог быть неудачным 0, 1 или более раз!), то разрез достигается, все ожидающие точки выбора создаются вами. Goal
отбрасываются, и вам это удается «раз» и навсегда.
См. swi-prolog.discourse.group/t/programming-cooperation/5623/…