Удалить список s (s (0)) в списке

(Это вопрос к этому вопросу).

Как написать lead1(Xs,Ys), который является истинным, iff Ys является суффиксом Xs со всеми удаленными терминами s(s(0)). Таким образом, вместо удаления ведущего 0 теперь возникает вопрос об удалении ведущего s(s(0)) s.

По сравнению с исходным вопросом трудность заключается здесь в правильном рассмотрении случаев s(X) и s(s(X)).

Ответ 1

Здесь версия с if_/3 и =/3:

list_suffix([],[]).
list_suffix([X|Xs],S) :-
   if_(X=s(s(0)), list_suffix(Xs,S), S=[X|Xs]).

Запросы с наземным первым аргументом детерминистически детерминированы:

?- list_suffix([s(0)],S).
S = [s(0)].

?- list_suffix([s(0),s(s(0))],S).
S = [s(0), s(s(0))].

?- list_suffix([s(s(0)),s(0),s(s(0))],S).
S = [s(0), s(s(0))].

?- list_suffix([s(s(0)), s(s(0)),s(0),s(s(0))],S).
S = [s(0), s(s(0))].

Если список состоит из слова, отличного от s/1, скажем, f(_), второй список идентичен первому:

?- list_suffix([f(_)],S).
S = [f(_G201)].

?- list_suffix([f(_)],[]).
false.

Также выполняются частично созданные экземпляры списков:

?- list_suffix([X, s(s(0)),s(0),s(s(0))],S).
X = s(s(0)),
S = [s(0), s(s(0))] ;
S = [X, s(s(0)), s(0), s(s(0))],
dif(X, s(s(0))).

Самый общий запрос работает, но перечисляет ответ несправедливо:

?- list_suffix(X,Y).
X = Y, Y = [] ;
X = [s(s(0))],
Y = [] ;
X = [s(s(0)), s(s(0))],
Y = [] ;
X = [s(s(0)), s(s(0)), s(s(0))],
Y = [] ;
.
.
.

Однако это может быть исправлено путем префикса длины цели /2:

?- length(X,_), list_suffix(X,Y).
X = Y, Y = [] ;
X = [s(s(0))],
Y = [] ;
X = Y, Y = [_G155],
dif(_G155, s(s(0))) ;
X = [s(s(0)), s(s(0))],
Y = [] ;
X = [s(s(0)), _G79],
Y = [_G79],
dif(_G79, s(s(0))) ;
X = Y, Y = [_G155, _G158],
dif(_G155, s(s(0))) ;
X = [s(s(0)), s(s(0)), s(s(0))],
Y = [] ;
.
.
.

Ответ 2

Hiere - это адаптация моего ответа на предыдущий вопрос. Он показывает использование, когда /2 вместо замораживания /2. freeze/2 следует за условием nonvar/1 для первого аргумента. когда /2 может следовать более сложным условиям.

lead(X, Y) :- var(X), !, freeze(X, lead(X,Y)).
lead([X|Y], Z) :- \+ ground(X), !, when(ground(X), lead([X|Y],Z)).
lead([s(s(0))|X], Y) :- !, lead(X, Y).
lead(X, X).

Вот несколько примеров, я собираю похожие примеры, как в моем ответе, который я дал предыдущему ответу. Мы видим, как когда /2 адаптирует свое собственное условие, когда аргумент списка постепенно создается:

?- lead([s(0),s(s(0)),s(s(0)),s(0)],Y).
Y = [s(0), s(s(0)), s(s(0)), s(0)].

?- lead([s(s(0)),s(s(0)),s(s(0)),s(0)],Y).
Y = [s(0)].

?- lead([X,s(s(0)),s(s(0)),s(0)],Y), X=s(_).
X = s(_G3686),
when(ground(_G3686), lead([s(_G3686), s(s(0)), s(s(0)), s(0)], Y)).

?- lead([X,s(s(0)),s(s(0)),s(0)],Y), X=s(0).
X = s(0),
Y = [s(0), s(s(0)), s(s(0)), s(0)].

?- lead([X,s(s(0)),s(s(0)),s(0)],Y), X=s(s(_)).
X = s(s(_G3713)),
when(ground(_G3713), lead([s(s(_G3713)), s(s(0)), s(s(0)), s(0)], Y)).

?- lead([X,s(s(0)),s(s(0)),s(0)],Y), X=s(s(0)).
X = s(s(0)),
Y = [s(0)].

замораживание/2, а при /2 - примитивы corouting. Их чистота хорошо документирована в литературе. Согласно этому источнику первая система Prolog с обработкой была Prolog-II со своим примитивом geler/2. Источник также упоминает о важности сопроцессора для решателей ограничений загрузки.

Предположим, что чистота протестирована с коммутативностью, вот пример теста:

?- lead([X,s(s(0)),s(s(0)),s(0)],Y), X=s(s(0)).
X = s(s(0)),
Y = [s(0)].

?- X=s(s(0)), lead([X,s(s(0)),s(s(0)),s(0)],Y).
X = s(s(0)),
Y = [s(0)].

Но замораживайте /2, и когда /2 не обязательно гарантируют полноту, как я уже писал в своем первом ответе, нам может понадобиться что-то сделать "в конце". Значит, после запроса у нас может быть множество барахтающихся целей. В программировании ограничения мы начали бы маркировать.

Также замораживать /2 и когда /2 не может найти ранний сбой, комбинируя цели, как могут сделать решатели ограничений.

Вышеприведенный eexample работает с SWI-Prolog без какого-либо импорта, а в Jekejeke Prolog используется Minlog Extension и импортировать библиотеку (term/suspend).