Поскольку вы понимаете max/3
, это не будет объяснено.
maxlist( [X], X). %what does this line do?
maxlist( [X,Y|Rest], Max):-
maxlist( [Y|Rest], MaxRest),
max(X, MaxRest,Max).
Это классический шаблон рекурсивного списка, который выполняет рекурсию перед обработкой элемента.Обычный шаблон рекурсивного списка с хвостовым вызовом -
process_list([H|T],R) :-
process_item(H,R),
process_list(T,R).
process_list([],R).
, но здесь это
process_list([H|T],R) :-
process_list(T,R),
process_item(H,R).
process_list([],R).
, где элемент обрабатывается после повторения в списке.
Также это обрабатывает два элемента одновременно, то есть
[H1,H2|T]
, потому что для сравнения нужны два элемента.
Этот
maxlist( [X,Y|Rest], Max):-
maxlist( [Y|Rest], MaxRest),
просто снимает значения сперечислите и поместите их в стек, чтобы при возврате он имел одно значение для сравнения, то есть MaxRest
, что является максимумом всех значений, которые были в Rest
, и текущее значение X
.Вы можете подумать, что это должно быть Y
, но когда в списке есть только один элемент, список на самом деле [Y|[]]
, который действительно [Y]
с совпадениями с шаблоном в этом пункте maxlist( [X], X).
.
Так что же делает maxlist( [X], X).
?Обычным базовым случаем для списка является просто predicate([],R).
для возврата списка, но в этом случае в качестве значения должно быть возвращено только одно последнее значение, поэтому это вынимает X
из списка в первом параметре и возвращает егов качестве значения во втором параметре, так что оно становится MaxRest
, что является максимальным значением, когда в списке есть только один элемент.Когда выполняется max(X, MaxRest,Max)
, он имеет значение для MaxRest
возврата из обратного отслеживания и X
в стеке при деконструкции списка.В результате получается Max
, который возвращается как третий параметр в maxlist( [X,Y|Rest], Max)
, который становится значением для MaxRest
при повторном возврате.
Задавать вопросы, если это не имеет смысла.
Я не понимаю, почему Пролог не выдает ошибку при объединении [X, Y | Rest] с [Y | Rest].
Пример [1,3, [7,2]] с [3 | [7,2]]
На самом деле
?- [1,3,[7,2]] = [3|[7,2]].
false.
, так что пока вашпример дает ошибку, это не то, что делается с
[X,Y|Rest] and [Y|Rest]
Начните со списка [1,2,3,4]
и объедините его с [X,Y|Rest]
?- [1,2,3,4] = [X,Y|Rest].
X = 1,
Y = 2,
Rest = [3, 4].
Обратите внимание, что [Y|Rest]
тогда будет [2|[3,4]]
.
?- [1,2,3,4] = [X,Y|Rest],A = [Y|Rest].
X = 1,
Y = 2,
Rest = [3, 4],
A = [2, 3, 4].
Не пытайтесь объединить [X,Y|Rest]
с [Y|Rest]
, а вместо этого объедините Rest
с Rest
и Y
с Y
, X
хранится в стеке, ноне передается на следующий уровень стекафрейма .
Если вы действительно хотите понять список, используйте его, чтобы увидеть их
?- write_term([1,2,3,4],[dotlists(true)]).
.(1,.(2,.(3,.(4,[]))))
true.
Если у вас есть версия 4книгу см. рис. 3.1 на стр. 61.