test consulted
да
?- обр([a,b,c,d],X).
нет
?- listing(обр).
обр([],[]).
обр ([_44|_45],_38):-обр(_45,_47),присоединить(_47,[_44],_38).
да
Печать утверждений предиката обрпоказывает, что атом присоединитьнаписан в программе с ошибкой.
clause(X, Y)
Выполнение целевого утверждения вида clause(X, Y)приводит к тому, что Xи Yсопоставляются с заголовком и телом некоторого имеющегося в базе данных утверждения. При попытке выполнить указанное целевое утверждение переменная Xдолжна быть до такой степени конкретизирована, чтобы был известен главный предикат утверждения. Если для данного предиката нет утверждений, то доказательство согласованности целевого утверждения заканчивается неудачей. Если имеется несколько утверждений, соответствующих предикату, то Пролог выбирает первое из них. В этом случае если предпринимается попытка вновь согласовать целевое утверждение, то будет выбрано следующее утверждение и так далее.
Заметим, что в то время как предикат clauseвсегда имеет аргумент, соответствующий телу утверждения, далеко не каждое утверждение действительно имеет тело. Если утверждение не имеет тела, то считается, что оно имеет фиктивное тело true.Мы называли такие утверждения «фактами». В той или иной степени конкретизируя Xи Y, можно искать либо все утверждения, соответствующие данному предикату с вполне определенным числом аргументов, либо все утверждения, соответствующие некоторому образцу. Так, например:
присоединить([], X, X).
присоединить([А|В]),С,[А|D]:- присоединить(В,С,D).
?- clause(присоединить(А,В,С),Y).
А=[], В =_23, С=_23, Y = true;
А = [_23|_24], В =_25, С = [_23|_26], Y = присоединить(_24,_25,_26);
нет
Предикат clauseочень полезен в том случае, если нам надо создать программы, анализирующие или исполняющие другие программы (см. разд. 7.13).
asserta(X), assertz(X)
Два встроенных предиката assertaи assertzпозволяют добавлять новые утверждения в базу данных. Оба предиката действуют в точности одинаковым образом, за тем исключением, что assertaдобавляет утверждение в начало базы данных, в то время как assertzдобавляет утверждение в ее конец. Это отличие можно легко запомнить, учитывая, что « а» является первой буквой английского алфавита, a « z» его последняя буква. При выполнении целевого утверждения asserta(X), Xдолжно иметь значением нечто, что можно представлять как утверждение; действительно, как и в случае clause, Xдолжно быть достаточно конкретизировано, чтобы можно было установить главный предикат. Необходимо подчеркнуть, что результат добавления в базу данных утверждения не устраняется при выполнении возврата. Следовательно, если мы использовали предикат assertaили assertzдля того, чтобы добавить новое утверждение, то это утверждение может быть удалено только в случае, если мы явно укажем это (используя предикат retract).
retract(X)
Встроенный предикат retractпозволяет удалять утверждения из базы данных. Этот предикат имеет один аргумент, представляющий терм, с которым должно быть сопоставлено удаляемое утверждение. Указанный терм должен быть достаточно конкретизирован, чтобы можно было определить предикат утверждения (аналогично предикатам asserta, clauseи т. д.). При попытке выполнить целевое утверждение retract(X)находится первое утверждение в базе данных, с которым может быть сопоставлен X, и это утверждение удаляется. При попытке вновь выполнить это целевое утверждение Пролог просматривает базу данных, начиная с места удаленного утверждения, в попытке найти другое сопоставимое утверждение. Если такое утверждение находится, то выполняются действия, рассмотренные выше. Если делается новая попытка согласовать целевое утверждение, то продолжается поиск следующего подходящего утверждения. И так далее. Заметим, что если утверждение было удалено, то оно ни при каких условиях не будет восстановлено вновь, даже при попытке вновь выполнить предикат retractпри возврате. Если в некоторый момент поиск не дает новых сопоставлений утверждений, то согласование целевого утверждения заканчивается неудачей.
Так как аргумент Xсопоставляется с удаляемым утверждением, то имеется возможность получить точное представление об удаляемом утверждении, даже если Xисходно означал некоторую структуру, содержащую множество неконкретизированных переменных. Это позволяет использовать предикат retractвместо предиката clause, в ситуации когда найденное утверждение сразу же удаляется. Такая ситуация как раз имеет место в определении предиката генатом (разд. 7.8).
Читать дальше