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

Теперь объединим все вместе

Вероятно, это самая сложная часть. К счастью, задача объединения

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

сложной как в более традиционных языках. Благодаря работе на более высо-

ком уровне абстракции, и не имея глобальной области данных, отделенной от

традиционной глобальной базы данных, различные части программы легко вза-

имодействуют друг с другом.

Например, чтобы поместить в интерпретатор базу правил, надо:

1. Преобразовать файл в строку с помощью предиката file_str.

2. С помощью сканнера преобразовать строку в список знаков.

3. С помощью транслятора преобразовать список знаков в терм.

4. Поместить термы в базу данных.

Это в основном то, что включает consulting (обсуждение файла), как и

показано ниже:

predicates

cons(string)

parse_clauses(TOKL)

clauses

parse_clauses(TOKL):-

s_lowerterm(TOKL,TOKL1,ATerm),!,

assertclause('0',ATerm),

parse_clauses(TOKL1).

parse_clauses(_).

cons(FIL):-

file_str(FIL,TXT),

tokl(0,TXT,TOKL),!,

parse_clauses(TOKL).

cons(_).

Обсуждение имени файла FIL с помощью вызова предиката cons в точнос-

ти совершает только что описанные действия. Для других реализаций меха-

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

ний.

Начало выполнения тогда заключается в вызове unify_body с нужной ги-

потезой. В нашем интерпретаторе Пролога это выполняется предикатом

handle_usergoal, вызываемом из run:

run:-

/* ... */

readln(FIRSTL),

repread(FIRSTL,L),

init_counter,

tokl(0,L,TOKL),

s_term(TOKL,_,ATerm),

trap(handle_usergoal(ATerm),E,errorhnd(E)),

traceflag, % If trace is turned on show the trace window

shiftwindow(3),

write("Press any key\n"),

readchar(CH), unreadchar(CH),

shiftwindow(2),

fail.

handle_usergoal(cmp(":-",[HEAD,BODY])):-!,

convhead(Head,Head1),

assert(clause(Head1,Body)),

write("Asserted").

handle_usergoal(ATerm):-

free(Env),

getbacktrack(Btop),

unify_body(ATerm,Env,Btop),

wenv(Env),nl,

count,

free(Env),

% Give only one solution when there are no variables

cutbacktrack(Btop),

fail.

handle_usergoal(_):-

closefile(seeing),

closefile(telling),

retractall(traceflag),

counter(X),

wsol(X).

repread - это readln со встроенным повторением. Строка ввода преоб-

разуется в список знаков, который с помощью s_term транслируется в терм и

помещается в handle_usergoal.

Так как это интерпретатор Пролога, то в особом случае цель имеет

форму Head:- Body; такое предложение должно быть помещено в базу данных.

Оно не вызывает никакие дальнейшие оценки - отсюда появляется первое

предложение handle_usergoal. Подобным образом, последнее предложение

handle_usergoal поддерживает порядок в цели пользователя.

Настоящим началом оценки гипотезы служит вызов unify_body во втором

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

первой точки возврата. Мы выбрали разработку обычных случаев, встречаю-

щихся в различных интерпретаторах Пролога, в которых избегается возврат в

цели пользователя, когда переменные не были определены. Остается открытым

вопрос, можно ли оправдать такое сужение задачи.

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

ствуют, то может существовать только одно видимое решение (Да или Нет),

которое вполне корректно, если осуществляется проверка на отсутствие по-

бочных эффектов. Когда обнаруживаются побочные эффекты, то это может слу-

жить поводом к нахождению всех решений, хотя ничего не будет возвращено в

цель пользователя в форме различных установок переменных.

В любом случае, фрагмент free(Env) отслеживает отсечение

backtracking, если не определены переменные. Предикат cutbacktrack окажет

плохую услугу, когда связанный с ним fail пошлет выполнение в последнее

предложение за пределы вершины предложения.