, так как вы сказали, что add / 3 завершается неудачно после второй итерации, я предполагаю, что вы в любом случае использовали trace / 0
, вот оно:
[trace] ?- doStuff([[1,2], [3,4], [5,6], [7,8]], R).
Call: (6) doStuff([[1, 2], [3, 4], [5, 6], [7, 8]], _G405) ? creep
Call: (7) lists:reverse([3, 4], _G496) ? creep
Exit: (7) lists:reverse([3, 4], [4, 3]) ? creep
Call: (7) add([1, 2], [4, 3], _G405) ? creep
Exit: (7) add([1, 2], [4, 3], [[1, 2], [4, 3]]) ? creep
Call: (7) doStuff([[5, 6], [7, 8]], [[1, 2], [4, 3]]) ? creep
Call: (8) lists:reverse([7, 8], _G514) ? creep
Exit: (8) lists:reverse([7, 8], [8, 7]) ? creep
Call: (8) add([5, 6], [8, 7], [[1, 2], [4, 3]]) ? creep
Fail: (8) add([5, 6], [8, 7], [[1, 2], [4, 3]]) ? creep
Redo: (7) doStuff([[5, 6], [7, 8]], [[1, 2], [4, 3]]) ? creep
Fail: (7) doStuff([[5, 6], [7, 8]], [[1, 2], [4, 3]]) ? creep
Redo: (6) doStuff([[1, 2], [3, 4], [5, 6], [7, 8]], _G405) ? creep
Fail: (6) doStuff([[1, 2], [3, 4], [5, 6], [7, 8]], _G405) ? creep
false.
так почему же это не удается?это из-за одной из основных характеристик пролога: переменная в прологе, когда она принимает значение, она никогда не может изменить это, может показаться странным, если вы до сих пор использовали императивные языки, но учтите, что в математике происходит то же самое.
Например, рассмотрим следующие уравнения:
x+3=4
4-x=5
из первого мы получаем, что x = 1
, а из второго мы получаем, что x = -1
, поскольку x не может быть 1 и-1 мы говорим, что x не удовлетворяет вышеприведенным уравнениям;
не то, что x равно -1, поскольку это значение второго (и последнего) уравнения
точно так же происходит в вашей программе:
doStuff([X,S|T],R):- reverse(S,Rev), add(X,Rev,R), doStuff(T,R).
, поэтому в первый раз R присваивается значение, а doStuff / 2 является вызовом со значением для R.
очевидно, это неверное значение, поэтому doStuff / 2 завершается сбоем
так как вы можете это исправить?посмотрите, как вы написали [X, S | T], чтобы отделить первые два элемента, которые вы хотели обработать.вам нужно сделать то же самое с результатом:
напишите его как [XResult, SResult | Rest], конечно, XResult будет просто X, а SResult будет противоположностью S (Rev)
Rest будет тем, чемвы получаете от рекурсивного вызова doStuff / 2
в последнюю очередь, но не в последнюю очередь вы должны проверить пункты, которые вызываются в конце.
вы можете проверить кое-что о lists и рекурсия