Вместо того, чтобы пытаться изменить поведение языка (что может быть возможно, но, конечно, является проблемой), было бы лучше выяснить, почему в конечном итоге Пролог находит C
с C == 1
.Если мы сами оценим maplist(num_x, A, B)
, то увидим:
?- maplist(num_x, [[x, o, o], [o, o, o], [o, o, x]], B).
B = [1, 0, 1] ;
B = [1, 0, 0] ;
B = [0, 0, 1] ;
B = [0, 0, 0].
Таким образом, получается, что предикат num_x/2
может генерировать несколько результатов для одного и того же списка: для списка с одним x
сначала генерируется 1
, а затем 0
.
Это подтверждается, если мы проведем несколько тестов с count/3
:
?- count([x, o, o], x, C).
C = 1 ;
C = 0.
?- count([x, x, o], x, C).
C = 2 ;
C = 1 ;
C = 1 ;
C = 0.
Таким образом, кажется, что count/3
каждыйвремя имеет точку возврата, где оно может решить подсчитать данный x
или нет.
Действительно, если мы посмотрим на предикат count/3
, мы увидим:
count([],X,0).
count([X|T],X,Y):- count(T,X,Z), Y is 1+Z.
count(<b>[_|T]</b>,X,Z):- count(T,X,Z).
Так что здесь для непустого списка есть два предложения way: одно, где head равен X
, элемент, который мы хотим считать, в этом случае Y is 1+Z
, но последнее предложение говорит, что независимо отКакова ценность головы, Пролог не будет считать этот элемент.Prolog выполняет откат назад и, таким образом, в конечном итоге выберет оба предложения.
Мы можем добавить dif/2
, чтобы добавить ограничение на то, что заголовок и X
должны быть dif ferrent, например:
count([],X,0).
count([X|T],X,Y):- count(T,X,Z), Y is 1+Z.
count(<b>[H|T]</b>,X,Z):- <b>dif(H, X)</b>, count(T,X,Z).
Так что теперь, если в списке появится X
, мы будем считать этот элемент.