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

На помощь приходит команда "cut"

Вероятно, вы сейчас думаете, что невозможно гарантировать, что про-

цедура является хвостовой рекурсией. Хотя, довольно просто сделать рекур-

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

ровать, что в любых других вызываемых процедурах нет альтернатив?

К счастью, внутренняя команда на завершение (!) позволяет отвергать

все существующие альтернативы. Чтобы установить ее, необходимо использо-

вать директиву компилятора check_determ. (Директивы компилятора описаны в

Справочном руководстве.)

Вы можите установить badcount3 следующим образом (изменяя его имя в

процессе) и оставляя check без изменений:

сutcount3(X) :-

write(X), nl,

NewX = X+1,

check(NewX),

!,

cutcount3(NewX).

Команда "cut" означает - "сжечь мосты между собой", или, точнее -

"однажды достигнув этой точки, не обращать внимание на альтернативные

предложения этого предиката и альтернативные решения предыдущих подцелей

включая данное предложение". Что точнее - решайте сами. Поскольку альтер-

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

дальше.

"Cut" также эффективен и в badcount2:

cutcount2(X) :-

X >= 0, !,

write(X), nl,

NewX = X+1,

cutcount2(NewX).

cutcount2(X) :-

write("X is negative.).

Если "cut" выполняется, компьютер предполагает, что непроверенных

альтернатив нет, и не создает стек.

/* Программа CH07EX06.PRO */

/* Показывает, как bedcount2 и bedcount3 может быть установлен объ-

явлением "cut" для исключения непроверенных предложений. Эти версии -

хвостовая рекурсия. */

predicates

cutcount2(real)

cutcount3(real)

check(real)

clauses

/* cutcount2:

Выполнение этого предложения не завершается во время ре-

курсивного вызова. */

cutcount2(X) :-

X >= 0, !,

write(X),

nl,

NewX = X+1,

cutcount2(NewX).

cutcount2(_) :-

write("X is negative.").

/* cutcount3:

Непроверенная альтернатива в предложении, вызванном перед

рекурсивным вызовом. */

cutcount3(X) :-

write(X),

nl,

NewX = X+1,

check(NewX),

!,

cutcount3(NewX).

check(Z) :- Z >= 0.

check(Z) :- Z > 0.

К сожалению, "cut" не сможет помочь с badcount1, которому необходи-

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

Единственный способ усовершенствовать badcount1 - представить вычисление

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