1.5.4. УПРАВЛЕНИЕ ПЕРЕХВАТОМ НЕУСПЕХОВ

Как мы видели выше, Рефал Плюс предоставляет довольно богатый набор конструкций для перехвата неуспехов. Однако, иногда возникает желание породить неуспех такой силы, чтобы он смог преодолеть все ловушки, расставленные для его перехвата (или хотя бы часть из них). Для этого служат заборы и отсечения.

Заборами называются хвосты вида \? Q , а отсечениями - хвосты вида \! Q . Заборы и отсечения являются пометками в программе, позволяющими управлять распространением неуспехов. А именно, всякое отсечение \! Q должно находиться внутри некоторого забора \? ... \! Q ... .

Вычисление отсечения \! Q производится следующим образом. Первым делом вычисляется тропа Q. Если это вычисление завершается с некоторым результатом X, этот результат считается результатом всей конструкции

\? ... \! Q ... .

В частности, если X - неуспех, то неуспехом заканчивается и вычисление всей конструкции \? ... \! Q ... .

Рассмотрим пример, иллюстрирующий использование заборов и отсечений. Предположим, что мы пытаемся вычислить следующую тропу:

eA : e1 '+' e2 '-' e3

= (e1)(e2)(e3)

Если значение переменной eA содержит '+' а вслед за ним и '-' на нулевом уровне скобок, то в результате сопоставления с образцом будут найдены самый левый '+' и ближайший за ним '-', после чего вычисление тропы успешно завершается. Теперь рассмотрим случай, когда eA содержит '+' на нулевом уровне, но не содержит на нулевом уровне ни одного '-'. Тогда первым делом будет найден первый '+', а затем будет просмотрена вся оставшаяся часть выражения, чтобы найти '-'. Поскольку это сделать не удастся, будет выполнено удлинение значения переменной e1, после чего снова будет выполнен поиск '-' в оставшейся части выражения. Между тем, этого можно было бы и не делать, ибо если '-' не нашелся первый раз, он заведомо не найдется и во второй раз. Мы можем избежать такого перебора с помощью \? и \!. Для этого, первым делом разобьем исходную перестройку на две части:

eA : e1 '+' еX,

eX : e2 '-' e3

= (e1)(e2)(e3)

Теперь, если сопоставление значения eX с образцом e2 '-' e3 завершается неуспешно, делается попытка испробовать следующий вариант сопоставления для eA : e1 '+' еX. Этого, однако, можно избежать, добавив \? и \! следующим образом:

\? eA : e1 '+' еX

\! eX : e2 '-' e3

= (e1)(e2)(e3)

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