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

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

В Прологе интерпретатор делает следующее:

1. Преобразует факты и правила в термы.

2. Отмечает некоторые термы для определенных действий.

3. Помещает термы в интерпретатор.

4. Совершает соответствующее действие с отмеченными термами

(оценивает факты и правила).

В таком контексте символы, обычно используемые в Прологе для струк-

турных правил (":-", ";", и ","), просто сообщают интерпретатору правил

порядок оценивания термов.

Пример интерпретации правил Прологом:

Правило

greet:- write(Hello there"), nl.

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

cmp(":-",[atom("greet"),

cmp(",",[cmp("write",[str("Hello there")]),atom("nl")])])

который можно поместить в базу данных или считать оттуда. Такой статичес-

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

татору Пролог как-нибудь была бы дана инструкция считать greet целью (мы

это обсудим позже), то он бы искал терм, соответствующий (который можно

унифицировать) следующему предложению:

cmp(":",[atom("greet"),Body])

Терм, представляющий greet:- write(Hello there"), nl, был сохранен в

базе данных, поэтому он может быть возвращен и унифицирован с другим тер-

мом. Здесь выполняется унификация переменной Body с термом, представляю-

щим тело предложения, которое выглядит так:

cmp(",",[cmp("write",[str("Hello there")]), atom("nl")])

Этот подтерм потом снова может быть направлен в интерпретатор, кото-

рый запрограммирован распознавать терм "запятая" (",") как "сначала про-

интерпретируй первый аргумент, а затем - второй аргумент".

Обратите внимание, что терм "запятая" всегда имеет два аргумента.

Если тело имеет только одну подцель, то функтор "запятая" отсутствует;

если имеется две или более подцели, то вторая и последующие будут иметь

свои собственные запятые во втором аргументе, что аналогично построению

списков с помощью функтора list.

Если бы write не был встроенным предикатом, распознаваемым интерпре-

татором, то интерпретация подцели:

write("Hello there")

привела бы к поиску определения предложения с заголовком:

cmp("write",[str("Hello there")])

Но так как write - встроенный предикат, а, следовательно, является

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

выполнения инструкций, совершающих реальные действия, указанные в write.

На этом интерпретация подцели заканчивается.

Возвращаясь к вызывающему предикату (greet), интерпретатор "интерп-

ретирует второй аргумент" и выполняет инструкции для nl, которые, также

как и для write, являются встроенными и конечными.

Если бы nl не был встроенным, то его интерпретация заключалась бы в

нахождении предложения, определяющего его, затем в интерпретации тела

этого предложения и т.д. до оконечных вызовов.

Естественно, в этом нет ничего нового: это обычный способ действий

при применении обратной цепочки рассуждений к набору правил. Но, тем не

менее, многие люди не знакомы с основами этого процесса и способами его

моделирования.

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

терпретатор правил, нам надо объяснить задействованные термы.

Статические термы в сравнении с действительными (выполняемыми):

Есть разница между термами, хранимыми в базе данных и теми, которые

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

ходную область термов sTerm.

Статический терм не может содержать свободных переменных. Любая пе-

ременная в статическом терме неактивна и ни на что не ссылается. Стати-

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

Поэтому интерпретатор различает область sTerm и выполняемую область

aTerm. Объявление области aTerm делается так:

aTerm = reference /* ссылка распределяется в соответствии со

следующими альтернативами*/

var(vid);

cmp(refSymb,aTermList);

list(aTerm,aTerm); nill;

atom(refSymb);

int(refInt);

str(refStr);

char(refChar)

aTermList = reference aTerm*

В области aTerm refSymb и refStr - это указатели типа string, в то

время как refInt и refChar указатели типа integer и char соответственно.

Область aTerm в точности соответствует объявленной ранее области sTerm с

тем исключением, что в области sTerm содержатся только нессылочные пере-

менные.

Варианты sTerm Варианты aTerm

var(string); reference var(VID);

cmp(string, sTermList) reference cmp(refSymb,aTermList);

list(sTerm, sTerm); nill; reference list(aTerm,aTerm);nill;

atom(string); reference atom(refSymb);

int(integer); reference int(refInt);

str(string); reference str(refStr);

char(chfr); reference char(refChar)

sTermList = reference sTerm TERMList = reference aTerm

Даже со всеми этими ссылочными областями, действительные термы сох-

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

действительными и статическими термами заключается в том, что свободные

переменные в статических термах представляются с помощью своих имен в ви-

де var (<имя_переменной>) в то время как в действительных термах они

представляются свободными переменными (указателями на свободные адреса).