Заменить member1
с memberchk
и ваш код будет работать намного лучше. Причина удивит вас! Давайте добавим некоторые «отладочные printfs» к вашему member1/2
предиката:
member1(X,[H|_]) :- format('testing ~w == ~w?~n', [X,H]), X==H,!.
member1(X,[_|T]) :- format('looking in tail ~w for ~w~n', [T,X]), member1(X,T).
Кажется, работает хорошо, не так ли?
?- member1(bar, [foo,bar,baz]).
testing bar == foo?
looking in tail [bar,baz] for bar
testing bar == bar?
true.
Кстати, memberchk/2
делает то же самое:
?- memberchk(bar, [foo,bar,baz]).
true.
Ну, мы получаем "истинный". :) Но что произойдет, если я передам ему что-то странное, как переменную вместо списка?
?- memberchk(bar, V).
V = [bar|_G483709].
Ах, ну, memberchk/2
принимает это как своего рода утверждение, что это в верхней части списка (это потому, что он делает то, что member/2
делает, но только один раствор). Что делает member1/2
?
?- member1(bar, V).
looking in tail _G478121 for bar
testing bar == _G478129?
looking in tail _G478130 for bar
testing bar == _G478138?
looking in tail _G478139 for bar
testing bar == _G478147?
looking in tail _G478148 for bar
testing bar == _G478156?
looking in tail _G478157 for bar
testing bar == _G478165?
looking in tail _G478166 for bar
testing bar == _G478174?
looking in tail _G478175 for bar
testing bar == _G478183?
...
eventually, boom, stack depth exceeded
Удивительно, но ваш код действительно входит в этот случай! Обратите внимание на то, что у вас есть условия, определяющие переменные с одной стороны, а не другой:
(B1==B2 -> K is J + 1; K is J + 0, LB1=[B1],LB2=[B2]),
Какие ценности LB1
и LB2
считать, если B1 не равен B2? Они остаются неподготовленными! Затем несколько строк позже вы безоговорочно добавить их:
append(LA1,LB1,AB1),
append(LC1,LD1,CD1),
append(AB1,CD1,L1),
Так к этому моменту, L1 = LA1 + LB1 + LC1 + LD1, но LB1 это чистая переменная! Это может произойти с любыми ваших переменных LX1/LX2, а затем вы завершаете ввод member1/2
с каким-то отверстием в вашем списке!
Это не ошибка в Прологе, между прочим. Например, если вы хотите, например, оставить хвост списка списков неинтересных различий.
Теперь у меня есть ведра другого совета для вас, но я думаю, что мораль этой истории прямо сейчас заключается в том, что вы должны использовать встроенные предикаты, когда это возможно. :)
Немного невежливо указать на репо; лучше включить [минимальный пример] (http://stackoverflow.com/help/mcve).Подготовка минимального примера, вероятно, поможет вам изолировать проблему и, возможно, облегчит обе наши жизни. –
Не ответ, но некоторые из ваших предикатов имеют стандартные копии: 'member1/2' is' memberchk/2', я бы использовал 'sort/2' вместо' distinct/2', 'nonmember/2' Я бы заменил с '\ + member (...)'. Вы используете '!' Достаточно, чтобы меня нервничать, но я не видел там очевидных ошибок. Помимо этого, это не выглядит ужасно; Я бы использовал более мощные предикаты форматирования и больше отделял логику от презентации, но для новичков это выглядит очень хорошо. –