Я вижу только два пути решения этой проблемы.
Первый, который кажется более простым, состоит в том, чтобы собрать все решения в списке и сосчитать его.Я не уверен, почему вам не нравится этот вариант.Вы беспокоитесь об эффективности или что-то?Или просто присваивание?
Проблема в том, что без использования мета-логического предиката, подобного setof/3
, вам придется позволить Прологу связывать значения обычным способом.Единственный способ зацикливаться, если вы позволяете Прологу делать это, - это сбои, как в следующем:
numberofchildren(Person, N) :- parent(Person, _), N is N+1.
Это не сработает;сначала вы получите arguments not sufficiently instantiated
.Затем вы исправите это и получите что-то вроде этого:
?- numberofchildren(michael, N)
N = 1 ;
N = 1 ;
N = 1 ;
no.
Причина в том, что вам нужен Пролог, чтобы отследить, если он собирается пройтись по фактам один за другим, и каждый раз, когда он возвращается,он связывает все, что связывал с момента последнего выбора.Единственный известный мне способ передачи данных через этот барьер - это динамическое хранилище:
:- dynamic(numberofchildrensofar/1).
numberofchildren(Person, N) :-
asserta(numberofchildrensofar(0)),
numberofchildren1(Person),
numberofchildrensofar(N), !.
numberofchildren1(Person) :-
parent(Person, _),
retract(numberofchildrensofar(N)),
N1 is N + 1,
asserta(numberofchildrensofar(N1),
!, fail.
numberofchildren1(_).
Я не проверял это, потому что я думаю, что это довольно отвратительно, но, вероятно, его можно заставить работать, еслиэто не так.:)
В любом случае, я настоятельно рекомендую вам воспользоваться списком, если это возможно.