#prolog #predicate
#prolog #предикат
Вопрос:
list([]) :- !.
list([A|B], X) :- X = X 1, list(B, X).
У меня есть следующий предикат, и я хочу определить размер списка. Во втором предикате, когда я изначально запускаю предикат, X не инициализируется. Как я могу проверить, имеет ли X значение, прежде чем увеличивать его.
?-list([a,b,c,d,e,f,g],X).
В этом случае X должен возвращать 7
Комментарии:
1.
=
не является оператором присваивания в Prolog. Это унификация.X = X 1
указывает, что вы хотите объединить переменнуюX
с термином' '(X,1)
, который является циклической ссылкой. ЕслиX
является числовым, вы можете сказать,X1 is X 1
(обратите внимание, чтоX is X 1
это приведет к сбою, поскольку значениеX
не может быть значениемX 1
). Иlist([]) :-...
это проблема. Где второй аргумент? Ваше предложение other predicate принимает два аргумента дляlist
. Я бы также рекомендовал не использовать общий список именlist
. Если вы определяете связь между списком и его длиной, почему бы не вызвать ееlist_length
?2. Как насчет использования предопределенного предиката
length/2
?
Ответ №1:
В декларативных парадигмах создание экземпляра невозможно (если вы не используете datafact или что-то подобное), поэтому способ решить вашу проблему — объявить, что пустой список имеет размер 0:
list([],0) :- !.
list([A|B], X1) :- list(B, X0), X1 = X0 1.
Таким образом, вы знаете, что длина списка L равна 1 (длина L хвоста)
Ответ №2:
Что касается этой части вашего примера кода :
X = X 1
Очень распространенная ошибка для людей, впервые знакомых с Prolog .
`=» в Prolog означает «то же самое, что» .
Следовательно, приведенный выше сегмент кода объявляет «X совпадает с X 1» .
По крайней мере, это должно быть :
X = Y 1
Однако это не совсем то, что вам нужно, потому что :
?- Y = 2 , X = Y 1 .
X = Y 1
Y = 2
Чтобы заставить Prolog поместить результат математического вычисления с правой стороны в переменную с левой стороны, используйте _lhs_ is _rhs_
.
?- Y = 2 , X is Y 1 .
X = 3
Y = 2
Что касается вопроса
How can I check if X has a value before doing an increment to it.
when(ground(_variable_),(_thing_to_do))
это лучший из доступных вариантов .
Вот пример решения общей поставленной проблемы, в котором используются некоторые из этих концепций.
реализация
goal_expansion((_lhs_ =:= _rhs_),(when(ground(_rhs_),(_lhs_ is _rhs_)))) .
:- op(2'1,'yfx','list') .
_list_ list [size:_size_] :-
_list_ list [size:_size_,shrink:_shrink_] ,
_list_ list [size:_size_,shrink:_shrink_,size:_SIZE_] .
_list_ list [size:0,shrink:false] .
_list_ list [size:_size_,shrink:true] :-
when(ground(_size_),(_size_ > 0)) .
[] list [size:0,shrink:false,size:0] .
[_car_|_cdr_] list [size:_size_,shrink:true,size:_SIZE_] :-
(_SIZE_ =:= _size_ - 1) ,
(_size_ =:= _SIZE_ 1) ,
_cdr_ list [size:_SIZE_] .
тестирование
/*
?- L list Z .
L = [],
Z = [size:0] ? ;
L = [_A],
Z = [size:1] ? ;
L = [_A,_B],
Z = [size:2] ? ;
L = [_A,_B,_C],
Z = [size:3] ?
yes
?- L list [size:0] .
L = [] ? ;
no
?- L list [size:1] .
L = [_A] ? ;
no
?- L list [size:2] .
L = [_A,_B] ? ;
no
?- [] list [size:S] .
S = 0 ? ;
no
?- [a] list [size:S] .
S = 1 ? ;
no
?- [a,b] list [size:S] .
S = 2 ? ;
no
?- [a,b,c] list [size:S] .
S = 3 ? ;
no
?-
*/
Комментарии:
1. Известно ли вам о встроенном предикате
length/2
?