Он будет повторять попытку с ближайшей предыдущей подцели, которая произвела точку выбора , когда это удалось.К сожалению, это одна из самых интересных и разных вещей в Прологе, поэтому это не простой ответ.
После fail
Пролог должен начать резервировать вызовы, которые предшествовали сбою.В этом случае непосредственно предшествующая вещь - assertz(queue(GTVal))
.Пролог отменит это, когда вернется, но не будет пытаться повторить его, потому что это предикат детерминированный : он выдает только одно решение, поэтому нет причин для его повторения.Затем он возвращается к greater(GT, WorstVal, Val, GTVal)
.У меня нет кода передо мной, чтобы сказать вам, почему, но поведение, которое вы видите, говорит мне, что это также детерминированный предикат, поэтому в стеке не осталось точек выбора для повторной попытки Пролога здесь.Если какие-либо привязки были установлены, Пролог устранит их и вернется к call(Goal)
.Обратите внимание, что установление привязок само по себе не приводит к появлению точки выбора.Должны быть оставшиеся варианты.
call(Goal)
интересен, потому что он будет зависеть от того, что Goal
является ли это детерминированным или нет.Например, call(true)
является детерминированным, а call(member(X, [1,2]))
- нет.Поведение, которое вы видите, указывает на то, что это не так.Вы всегда можете получить полудетерминированное поведение (один успех или неудача), заключив свою цель в once/1
, как в once(call(Goal))
.Это самый простой и безопасный способ ввести сокращения в вашу программу;более общий механизм с оператором !
.