Удалить список 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).