Спецификаторы выбраны с таким расчетом, чтобы нагляднее отразить структуру выражения, в котором 'f' соответствует оператору, а 'x' и 'y' представляют его аргументы. Расположение 'f' между аргументами указывает на то, что оператор инфиксный. Префиксные и постфиксные спецификаторы содержат только один аргумент, который, соответственно, либо следует за оператором, либо предшествует ему.

Рис. op3.7.  Две интерпретации выражения а-b-с в предположении, что '-' имеет приоритет 500. Если тип '-' есть yfx, то интерпретация 2 неверна, так как приоритет b-с не выше, чем приоритет '-'.

Между 'x' и 'y' есть разница. Для ее объяснения нам потребуется ввести понятие приоритета аргумента. Если аргумент заключен в скобки или не имеет структуры (является простым объектом), тогда его приоритет равен 0; если же он структурный, тогда его приоритет равен приоритету его главного функтора. С помощью 'x' обозначается аргумент, чей приоритет должен быть строго выше приоритета оператора (т e. его номер строго меньше номера приоритета оператора); с помощью 'y' обозначается аргумент, чей приоритет выше или равен приоритету оператора.

Такие правила помогают избежать неоднозначности при обработке выражений, в которых встречаются операторы с одинаковым приоритетом. Например, выражение

а-b-с

обычно понимается как (а-b)-с, а не как а-(b-с). Чтобы обеспечить такую обычную интерпретацию, оператор '-' следует определять как yfx. На рис. 3.7 показано, каким образом исключается вторая интерпретация.

В качестве еще одного примера рассмотрим оператор not (логическое отрицание 'не'). Если not oпределён как fy, тогда выражение

 not not p

записано верно; однако, если not определен как fx, оно некорректно, потому что аргументом первого not является структура not p, которая имеет тот же приоритет, что и not. В этом случае выражение следует писать со скобками:

not (not p)

:- op( 1200, xfx, ':-').

:- op( 1200, fx, [:-, ?-] ).

:- op( 1100, xfy, ';').

:- op( 1000, xfy, ',').

:- op( 700, xfx, [=, is, <, >, =<, >=, ==, ==, ==, =:=]).

:- op( 500, yfx, [+, -] ).

:- op( 500, fx, [+, -, not] ).

:- op( 400, yfx, [*, /, div] ).

:- op( 300, xfx, mod).

Рис. 3.8. Множество предопределенных операторов.

Для удобства некоторые операторы в пролог-системах определены заранее, чтобы ими можно было пользоваться сразу, без какого-либо определения их в программе. Набор таких операторов и их приоритеты зависят от реализации. Мы будем предполагать, что множество этих 'стандартных' операторов ведет себя так, как если бы оно было определено с помощью предложений, приведенных на рис. 3.8. Как видно из того же рисунка, несколько операторов могут быть определены в одном предложении, если только они все имеют одинаковый приоритет и тип. В этом случае имена операторов записываются в виде списка. Использование операторов может значительно повысить наглядность, 'читабельность' программы. Для примера предположим, что мы пишем программу для обработки булевских выражений. В такой программе мы, возможно, захотим записать утверждение одной из теорем де Моргана, которое в математических обозначениях записывается так:

~ (А & В) <===> ~А v ~В

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

эквивалентно( not( и( А, В)), или( not( A, not( B))).

Однако хорошим стилем программирования было бы попытаться сохранить по возможности больше сходства между видом записи исходной задачи и видом, используемом в программе ее решения. В нашем примере этого можно достичь почти в полной мере, применив операторы. Подходящее множество операторов для наших целей можно определить так:

:- op( 800, xfx, <===>).

:- op( 700, xfy, v).

:- op( 600, хfу, &).

:- op( 500, fy, ~).

Теперь правило де Моргана можно записать в виде следующего факта:

~(А & В) <===> ~А v ~В.

В соответствии с нашими определениями операторов этот терм понимается так, как это показано на рис. 3.9.

Рис. 3.9. Интерпретация терма ~(А & В) <===> ~A v ~В

Подытожим:

• Наглядность программы часто можно улучшить, использовав операторную нотацию. Операторы бывают инфиксные, префиксные и постфиксные.

• В принципе, с оператором не связываются никакие действия над данными, за исключением особых случаев. Определение оператора не содержит описания каких-либо действий, оно лишь вводит новый способ записи. Операторы, как и функторы, лишь связывают компоненты в единую структуру.

• Программист может вводить свои собственные операторы. Каждый оператор определяется своим именем, приоритетом и типом.

• Номер приоритета — это целое число из некоторого диапазона, скажем, между 1 и 1200. Оператор с самым больший номером приоритета соответствует главному функтору выражения, в котором этот оператор встретился. Операторы с меньшими номерами приоритетов связывают свои аргументы сильнее других операторов.

• Тип оператора зависит от двух условий: (1) его расположения относительно своих аргументов, (2) приоритета его аргументов по сравнению с его собственным. В спецификаторах, таких, как xfyx обозначает аргумент, чей номер приоритета строго меньше номера приоритета оператора; y — аргумент с номером приоритета, меньшим или равным номеру приоритета оператора.

Упражнения

3.12. Если принять такие определения

:- op( 300, xfy, играет_в).

:- op( 200, xfy, и).

то два следующих терма представляют собой синтаксически правильные объекты:

Tepм1 = джимми играет_в футбол и сквош

Терм1 = сьюзан играет_в теннис и баскетбол и волейбол

Как эти термы интерпретируются пролог-системой? Каковы их главные функторы и какова их структура?

3.13. Предложите подходящее определение операторов ('работает', 'в', 'нашем'), чтобы можно было писать предложения типа:

Добавить отзыв
ВСЕ ОТЗЫВЫ О КНИГЕ В ИЗБРАННОЕ

0

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

Отметить Добавить цитату