Ваша проблема утверждение
Я пытаюсь добавить номер к каждому элементу в списке и подсписков. Список также содержит дерево (функтор не может быть числовым, только листья могут быть числовыми).
Вы не указали как представлены ваши «деревья». Однако это довольно простая проблема обхода. Вы можете сделать что-то очень общее, так, что будет принимать любой произвольный пролог срока и увеличиваете все числа, найденные в:
increment(X , Y , Z) :- number(X) , ! , Z is X+Y) .
increment(X , Y , Z) :- var(X) , ! , Z = X .
increment(X , Y , Z) :- atomic(X) , ! . Z = X . % atomic terms, including the empty list, remain unchanged.
increment(X , Y , Z) :- compound(X) , ! , % otherwise, we have a compound term, including a non-empty list...
X =.. [Functor|Args] , % - decompose the compound term into its functor and argument list
increment(Args,Y,Args1) , % - increment the argument list
Z =.. [Functor|Args1] , % - assemble the new, incremented compound term
. % Easy!
Вам не нужны в явной форме тестов для списков, как пустой список только атом '[]'
и непустой список [Head|Tail]
является просто синтаксическим сахаром для прологового термина '.'(Head,Tail)
, при этом соглашение состоит в том, что Tail
является либо пустым списком ([]
), либо другим непустым списком.
Однако, вы можете хотите явный тест для списков, поскольку я подозреваю, что многие (большинство?) Прологи имеют специальные реализации списков, чтобы повысить производительность.
Если вы хотите ограничить ваш increment/3
только списки, вы могли бы сделать что-то вроде этого, где increment/3
траверсы списка и применяете преобразование к каждому найденному элементу в пределах:
increment([] , _ , [] ) :-
increment([X|Xs] , Y , [Z|Zs]) :-
transform(X ,Y , Z ) ,
increment(Xs ,Y , Zs)
.
transform(X,Y,Z) :- var(X) , ! , Z = X .
transform(X,Y,Z) :- number(X) , ! , Z is X+Y .
transform(X,Y,Z) :- is_list(X) , ! , increment(X,Y,Z) .
transform(X,Y,Z) :- atomic(X) , ! , Z = Z .
transform(X,Y,Z) :- compound(X) , ! ,
X =.. [F|As] , % - decompose the compound term into its functor and list of arguments
increment(As,Y,A1) , % - increment the argument list
Z =.. [F|A1] % - assemble the incremented compount term
. % Easy!
is_list/1
является встроенным предикат для SWI Prolog. Если у вашего пролога нет его, тривиально сворачивать самостоятельно. Вот две реализации.
Это исчерпывающий тест на список. Он проверяет полное рекурсивное определение списка: список представляет собой либо атом []
, либо непустой список [H|T]
, где T
сам является списком. Это реализация используется SWI Prolog:
is_list( X ) :- var(X) , ! , fail . % variables are not lists
is_list( [] ) . % the empty list
is_list([_|T]) :- is_list(T) . % a non-empty list has a tail that is itself a list
Следует отметить, что для длинных списков, это может быть несколько дорогостоящей операцией, так как она требует прохождения всего списка. С этой целью вы можете использовать более простой тест, который выглядит только в самом верхнем срок:
is_list( X ) :- var(X) , ! , fail . % variables are not lists
is_list( [] ) . % the empty list
is_list( [_|_]) . % a non-empty list
Там опечатка в пункте 'istree (H): - istree (_, F) .'. Система Prolog, вероятно, напечатала предупреждение об одноэлементных переменных в этом разделе. –
Я тестировал этот фрагмент кода и отлично работает. Он показывает true, если данный термин является многодорожечным деревом. Можете ли вы сказать мне, где еще я могу ошибиться. – abc
Конечно, это правда! Вы вызываете предикат 'istree/2' с переменной во втором аргументе, что означает вызов' isforest/1' с переменным аргументом. –