logo
TurboProlog / Документация / TOM_2

Интерпретация тела правила

Получив средство снабжения машины вывода горючим, мы теперь рассмот-

рим, как его зажигать. Тело правила будет состоять из одной или несколь-

ких подцелей; этот раздел предназначен для рассмотрения пердиката

unify_body, отвечающего за интерпретацию структуры тела правила.

По существу это делается посредством:

1. Разбиения тела на подцели - в соответствии с порядком оцени-

вания, определяемого строением тела;

2. Вызова другого предиката, который отвечает за фактическое

выполнение отдельных подцелей.

Предикат unify_body является также высшим входом интерпретатора; для

интерпретации базы правил предикату unify_body задаются цель, которую

нужно удовлетворить (гипотеза) и свободная среда как аргументы, затем

этот предикат достигнет цели с успехом или нет в зависимости от того,

можно ли доказать гипотезу.

Объявление и определение минимальной конфигурации предиката

unify_body выглядит так:

PREDICATES

nondeterm unify_body(sTerm, Env, integer)

CLAUSES:

unify_body(cmp(",",[Term1, Term2]), Env, Btop):-!,

unify_body(Term1, Env, Btop),

unify_body(Term2, Env, Btop).

unify_body(cmp(";",[STerm,_]), Env, Btop):-

unify_body(STerm, Env, Btop).

unify_body(cmp(";",[_,STerm]), Env, Btop):-!,

unify_body(STerm, Env, Btop),

unify_body(cmp(PID, STermList), Env,_):-

unify_terml(Call, STermList), Env,_),

call(PID, Call).

unify_body(atom(PID), Env,_):- call(cmp(PID, []), Env).

Целый аргумент Btop должен взаимодействовать с выполняемой базой

правил, вызывая отсечение (cut); сейчас мы не будем обсуждать его. Обра-

тите внимание: отсечение не является действительной частью общего принци-

па работы цепочки с обратным рассуждением, поэтому в большинстве случаев

он не используется в изначальной интерпретации правил базы. Мы поговорим

о нем позже, когда будем рассматривать интерпретацию Пролога.

Во многих случаях для unify_body вам потребуются только описанные

выше предложения, при этом можно обойтись даже меньшим количеством.

Аргумент среды для unify_body - Env - это среда для предложения

(терма), интерпретируемого в данный момент (как обсуждалось выше); он

создается непосредственно перед вызовом unify_body (на уровне гипотезы

или цели).

Первое предложение unify_body делает это для терма "запятая": "про-

интепретируй первый аргумент (Term1), а потом проинтерпретируй второй ар-

гумент (Term2)". Интерпретация второго аргумента может вызвать тот же са-

мый процесс; если в теле предложения больше двух подцелей, то они будут

иметь свои собственные термы "запятая" во втором аргументе.

Следующие два предложения unify_body отвечают за редко используемую

дизъюнкцию. unify_body пытается проинтерпретировать первый терм; если это

не получается, то интерпретируется второй аргумент. Для изначальных баз

правил дизъюнкции не требуются, так как действие может быть выполнено с

помощью нескольких других предложений для того же правила. Если в вашей

конкретной задаче дизъюнкции не требуются, то можно удалить эти два пред-

ложения.

Для полноты мы включили в механизм вывода и форму отрицания. Это де-

лается с помощью следующего предложения unify_body:

unify_body(cmp("not",[ATerm]), Env,_):-

getbacktrack(Btop), not(unify_body(ATerm, Env< Btop)).

Причина вызова getbacktrack связана с проектируемым решением. Мы ре-

шили, что not(not(!)) будет вести себя также как true. Здесь требуется

использование getbacktrack для возвращения нового указателя возврата.

Приготовление динамического cut с помощью вызова getbacktrack включено

для завершения, чтобы позволить базе правил вызвать cut. В большинстве

случаев в этом нет необходимости.

Во всех этих случаях unify_body просто вызывает себя для получения

конкретного проинтерпретированного аргумента. Последние два предложения

unify_body вызывают Call (привод машины вывода), отвечающий за интерпре-

тацию того, чей функтор не подходит ни к одному предыдущему.

unify_body(cmp(PID, ATermList), Env,_):-

unify_terml(Call, ATermList), Env,_),

call(PID, Call).

unify_body(atom(PID), Env,_):-

call(cmp(PID, [], Env).

В первом предложении unify_body вызывается unify_terml для создания

списка aTerms (действительных термов) из списка sTerms (статических тер-

мов) для терма вопросов.

unify_terml возвратит активный список термов, связанных с аргументом

Call; этот активный список состоит из:

- свободных переменных, замененных на неустановленные перемен-

ные (разделяемых с переменными на элементах среды).

- термы среды, замененные связанными переменными.

Смысл всего этого заключается в том, что когда unify_terml вызывает-

ся со свободным аргументом aTerm (в этом случае аргумент aTerm - это пе-

ременная Call) и со связанным sterm, unify_terml создаст активный список

термов. Новые активные термы будут иметь связывание среды вместо перемен-

ных среды.