Как создать экземпляр переменной в предикате prolog

#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 ?