Предикат time_out/2
имеет только одну, рекурсивную, оговорку. Где базовое предложение? Этот рекурсивный пункт пересекает список. Предполагая, что предикат вызывается с закрытым списком, вы в конечном итоге будете вызывать предикат с пустым списком в качестве первого аргумента. Поскольку нет предложения с объединением головы с этой целью, вызов терпит неудачу.
Также обратите внимание, что ваше предложение не является хвостовым рекурсивным. То есть в этом случае есть цель после вызова рекурсивного вызова. Это означает, что эта цель должна быть сохранена в стеке (для каждого рекурсивного вызова) до тех пор, пока не будет найден базовый случай. Это пространство для отходов (линейное и число рекурсивных вызовов). Решение для преобразования вашего предиката в хвостовой рекурсивный предикат в этом случае (и в целом) используется для использования аккумулятора на расстоянии, которое вы вычисляете. Когда вы достигнете (отсутствующий базовый вариант), значение аккумулятора будет расстояние вы вычисления:
time_out(Stops, Distance) :-
% the initial value of the accumulator is zero
% as we're computing the sum of distances
time_out(Stops, 0, Distance).
time_out([], Distance, Distance).
time_out([(_, End1), (Start2, End2)| Stops], Distance0, Distance) :-
diff_t(Start2, End1, Leg),
Distance1 is Leg + Distance0,
time_out([(Start2, End2)| Stops], Distance1, Distance).
Но это определение не является правильным. Вы можете определить проблему? Что происходит, когда в списке содержится одна пара стартового конца? Вы можете исправить это определение? Возможно, у нас есть неправильный базовый чехол?
Большинство систем Пролог обеспечивают след особенность, которая часто помогает в понимании Пролога вычислений:
?- trace.
true.
[trace] ?- time_out([(_,1300),(1400,1600)],T).
Call: (7) time_out([ (_G2156, 1300), (1400, 1600)], _G2169) ? creep
Call: (8) time_out([ (_G2156, 1300), (1400, 1600)], 0, _G2169) ? creep
Call: (9) diff_t(1400, 1300, _G2261) ? creep
Call: (10) 1300>1400 ? creep
Fail: (10) 1300>1400 ? creep
Redo: (9) diff_t(1400, 1300, _G2261) ? creep
Call: (10) 1300=<1400 ? creep
Exit: (10) 1300=<1400 ? creep
Call: (10) _G2262 is 1300+2400 ? creep
Exit: (10) 3700 is 1300+2400 ? creep
Call: (10) _G2265 is 3700-1400 ? creep
Exit: (10) 2300 is 3700-1400 ? creep
Exit: (9) diff_t(1400, 1300, 2300) ? creep
Call: (9) _G2268 is 2300+0 ? creep
Exit: (9) 2300 is 2300+0 ? creep
Call: (9) time_out([ (1400, 1600)], 2300, _G2169) ? creep
Fail: (9) time_out([ (1400, 1600)], 2300, _G2169) ? creep
Fail: (8) time_out([ (_G2156, 1300), (1400, 1600)], 0, _G2169) ? creep
Fail: (7) time_out([ (_G2156, 1300), (1400, 1600)], _G2169) ? creep
false.
Посмотрите внимательно на вызов (9)
. Я дам вам до завтра, чтобы вы нашли решение этой ошибки. Счастливый взлом!
UPDATE
Теперь, когда ОП нашел рабочий раствор время, чтобы исправить это. Например, написав:
time_out([(_, End1)| Stops], Distance) :-
% the initial value of the accumulator is zero
% as we're computing the sum of distances
time_out(Stops, End1, 0, Distance).
time_out([], _, Distance, Distance).
time_out([(Start2, End2)| Stops], End1, Distance0, Distance) :-
diff_t(Start2, End1, Leg),
Distance1 is Leg + Distance0,
time_out(Stops, End2, Distance1, Distance).
Следует отметить, что большинство систем Пролога осуществить оптимизацию, называемой первого аргумент индексацией, что позволяет пробуя положения, которые могут быть в состоянии решить текущую задачу. Эта оптимизация обычно реализуется, рассматривая тип и, в атомных терминах, в некоторых случаях значение первого аргумента (если оно связано). Первый аргумент в двух положений для time_out/4
предиката, для первой, атом[]
(пустой список не список), а для второго список с одним или несколькими элементами. Таким образом, принимая эту оптимизацию, правильное предложение будет выбираться каждый раз при вызове этого предиката (с, конечно, с его первым аргументом, созданным экземпляром), тем самым избегая ложных точек выбора.Тем не менее, такая же оптимизация не применяется в случае вашего решения, так как в обоих предложениях для вашего предиката time_out/2
первым аргументом является список.
Пожалуйста, поясните, правильный ответ на примере вы предоставляете это? –