А не объединяется с чем-либо в теле ваших правил. Пролог работает через унификацию терминов. Вы не можете «вернуть» А как процедурные языки как таковые. Например, что вы хотите, чтобы значение A было, когда рекурсия заканчивается? Я понятия не имею, что делает ваш код, поэтому позвольте мне использовать мой собственный пример.
accumulate([], A, A).
accumulate([H|T], A, N) :- A1 is A + H, accumulate(T, A1, N).
sum([], 0).
sum(L, N) :- accumulate(L,0,N).
Вот процедура суммирования, которая будет суммировать значения в списке и «return N», сумму значений в списке. Для вызова этой процедуры вы можете сделать это:
sum([2, 3, 4], N).
И Пролог ответит:
N = 9
Обратите внимание, что процедура накопления использует A в качестве аккумулятора, когда продолжается рекурсия. Таким образом, A сохраняет промежуточную сумму, а N - окончательный ответ, который она возвращает. Во время рекурсии N не унифицируется ни с какой реальной ценностью.
На последнем этапе рекурсии, то есть, когда список пуст, значение A объединяется с N, фактически возвращая N.
Давайте сделаем След.
[trace] 4 ?- test(A, B, 0).
Call: (7) test(_G417, _G418, 0) ? creep//A unifies with _G417 (internal variable name), B with _G418 and N with 0.
Call: (8) nonvar(_G418) ? creep
Fail: (8) nonvar(_G418) ? creep
Redo: (7) test(_G417, _G418, 0) ? creep//Unifies with clause 2,
^ Call: (8) 0>2 ? creep
^ Fail: (8) 0>2 ? creep
Redo: (7) test(_G417, _G418, 0) ? creep //Unifies with clause 3
^ Call: (8) _L183 is 0+1 ? creep
^ Exit: (8) 1 is 0+1 ? creep
Call: (8) test(1, _G418, 1) ? creep //recursive call, unifies with
Call: (9) nonvar(_G418) ? creep
Fail: (9) nonvar(_G418) ? creep
Redo: (8) test(1, _G418, 1) ? creep
^ Call: (9) 1>2 ? creep
^ Fail: (9) 1>2 ? creep
Redo: (8) test(1, _G418, 1) ? creep
^ Call: (9) _L195 is 1+1 ? creep
^ Exit: (9) 2 is 1+1 ? creep
Call: (9) test(2, _G418, 2) ? creep
Call: (10) nonvar(_G418) ? creep
Fail: (10) nonvar(_G418) ? creep
Redo: (9) test(2, _G418, 2) ? creep
^ Call: (10) 2>2 ? creep
^ Fail: (10) 2>2 ? creep
Redo: (9) test(2, _G418, 2) ? creep
^ Call: (10) _L207 is 2+1 ? creep
^ Exit: (10) 3 is 2+1 ? creep
Call: (10) test(3, _G418, 3) ? creep
Call: (11) nonvar(_G418) ? creep
Fail: (11) nonvar(_G418) ? creep
Redo: (10) test(3, _G418, 3) ? creep
^ Call: (11) 3>2 ? creep
^ Exit: (11) 3>2 ? creep
Call: (11) test(3, final, 3) ? creep
Call: (12) nonvar(final) ? creep
Exit: (12) nonvar(final) ? creep
Call: (12) final=final ? creep
Exit: (12) final=final ? creep
Call: (12) true ? creep
Exit: (12) true ? creep
Exit: (11) test(3, final, 3) ? creep
Exit: (10) test(3, _G418, 3) ? creep
Exit: (9) test(2, _G418, 2) ? creep
Exit: (8) test(1, _G418, 1) ? creep
Exit: (7) test(_G417, _G418, 0) ? creep
Теперь обратите внимание на точку на трассе, где я отметил //A unifies with _G417 (internal variable name), B with _G418 and N with 0.
. В этот момент A - ваша внешняя переменная, а _G417 - ваша внутренняя A. Если этот вызов завершится успешно, то в конечном итоге пролог сообщит только о значениях внешней переменной. Внутренне _G417 никогда не объединяется ни с чем другим. Я думаю, что проблема заключается в понимании того, как работает модель объединения Пролога.