Для стандартного решения Prolog ISO вы можете использовать findall / 3 , чтобы создать список всех решений, а затем установить Count равным длине полученного списка. Может быть немного сложно заключить это в пользовательский предикат count / 2 , как вы предлагаете, потому что нам нужно сформировать первый аргумент findall / 3 таким образом, чтобы учитывает любые свободные (несвязанные) переменные в цели, которую вы хотите передать в качестве первого аргумента count / 2 .
Многие прологи предоставляют «счетчики» или другие формы изменяемых глобальных значений, нестандартное расширение, которые можно использовать в связи с «циклом», управляемым отказами, для выполнения одинакового подсчета. Чуть более громоздким, но придерживающимся буквы стандарта Prolog было бы использовать assert и retract , чтобы создать свой собственный "счетчик" путем корректировки динамического факта.
Ниже приводится иллюстрация последнего подхода. Чтобы сделать его «многопоточным безопасным», потребовалась бы дополнительная логика.
count(Goal,_) :-
setGoalCount(0),
call(Goal),
incGoalCount(1),
fail. /* or false in some Prologs */
count(_,Count) :-
getGoalCount(Count).
setGoalCount(_) :-
retract(getGoalCount(_)),
fail.
setGoalCount(X) :-
assert(getGoalCount(X)).
incGoalCount(Y) :-
retract(getGoalCount(X)),
!,
Z is X + Y,
assert(getGoalCount(Z)).