Пролог: циклы, управляемые отказом

Я использовал следующий цикл, управляемый ошибкой, чтобы перечислить все без использования точки с запятой.

happiness(fred,5).
happiness(john,3).
happiness(grace,2).

someGoal(X) :-
        happiness(X,Y), write(Y), tab(4), fail.

В режиме запроса я получаю это, как и ожидалось

?- someGoal(_).
5    3    2 

Как я могу вставить эти числа в список, а не выводить их на экран? Я не мог справиться с этим в someGoal, так как возврат назад кажется неявным.


person Zoran    schedule 24.10.2012    source источник


Ответы (2)


Вы правы, возвращаясь к тому, как Пролог обрабатывает альтернативы.

Используйте findall/3, которые собирают все альтернативы, использующие возврат «внутренне»:

someGoal(X, Values) :-
    findall(Value, happiness(X, Value), Values).

Затем ?- someGoal(_, Values). будет экземпляр Values ​​= [5, 3, 2]

person CapelliC    schedule 24.10.2012
comment
Спасибо, отлично, спас мой день. Я приобрел много навыков пролога, хотя и пытался наоборот: P - person Zoran; 25.10.2012

Циклы, вызванные отказом, часто оставляют некоторые части открытыми и неуказанными, что рано или поздно вызовет некоторые проблемы. В частности, точная количественная оценка переменных легко остается открытой. Часто таких циклов можно вообще избежать. В вашем примере мне непонятно, почему у вас вообще аргумент someGoal/1. По крайней мере, вы им не пользуетесь. Поэтому возникает несколько вопросов:

  1. Что вы ожидаете, если нет подходящего значения? Ваша исходная программа ничего не печатает и терпит неудачу.

  2. Что вы ожидаете, если есть избыточные записи? Хотите, чтобы вещи печатались несколько раз?

  3. Вы настаиваете на точном порядке значений или можете представить другой порядок?

  4. Почему вам вообще интересно видеть значения? В большинстве случаев вы либо хотите видеть их связанными с конкретными именами, либо вам нужна какая-то их совокупность, например сумма или среднее значение.

Учитывая, что я не знаю ответа на них, могу предложить вам несколько решений. Я возьму ваш пример с одним дополнительным (лишним) фактом:

happiness(fred,5).
happiness(john,3).
happiness(john,3).
happiness(grace,2).

?- setof(P-H,happiness(P,H), PHs).
PHs = [fred-5, grace-2, john-3].

?- setof(H,P^happiness(P,H), PHs).
PHs = [2, 3, 5].

?- bagof(H,P^happiness(P,H), PHs).
PHs = [5, 3, 3, 2].
person false    schedule 25.10.2012
comment
Большое спасибо за дополнительные разъяснения и разбор случая. Мой игрушечный пример уменьшен из более сложного для удобства чтения. - person Zoran; 25.10.2012