Незначительная несогласованность из-за различного приоритета операторов ** и ^

Почему приоритет аргумента **/2 (xfx) и (^)/2 (xfy ) не то же самое в Прологе?

Это приводит к незначительным несоответствиям, таким как следующее:

?- X = 1, Y is 1 ^ -X.
X = Y, Y = 1.

и

?- Y is 1 ** -1.
Y = 1.

а

?- X = 1, Y is 1 ** -X.
ERROR: Syntax error: Operator priority clash
ERROR: X = 1, Y is 1 *
ERROR: ** here **
ERROR: * -X .
7 голосов | спросил Wouter Beek 10 WedEurope/Moscow2014-12-10T02:06:43+03:00Europe/Moscow12bEurope/MoscowWed, 10 Dec 2014 02:06:43 +0300 2014, 02:06:43

3 ответа


0

Младшая точка: это (^)/2, а не ^/2, чтобы указать, что ^ используется в качестве оператора, и сделать его допустимым синтаксисом Пролога и индикатором предиката (7.1. 6.6).

(**)/2 и (^)/2 оба оцениваемые функторы (9), поэтому их можно использовать для арифметической оценки (8.7) с (is)/2 и арифметического сравнения (8.7) с (=:=)/2, (<)/2 и тому подобное. Их определения немного отличаются.

(**)/2 всегда возвращает число с плавающей точкой, как и (/)/2 всегда дает число с плавающей запятой. (SWI здесь не следует стандарту, у него есть свои соглашения).

?- X is 2**2.
X = 4.0.

?- X is 2/2.
X = 1.0.

(^)/2 здесь, чтобы разрешить целочисленное возведение в степень, которое стало намного более важным со многими системами, теперь поддерживающими произвольно большие целые числа. Подумайте о 2^2^X. То есть, если оба аргумента являются целыми числами, результат также является целым числом, точно так же, как (*)/2 обрабатывает этот случай.

?- X is 2^2, Y is 2*2.
X = 4, Y = 4.

?- X is 2.0^2, Y is 2.0*2.
X = 4.0, Y = 4.0.

В тех случаях, когда (^)/2 дает реальное значение с двумя целочисленными аргументами (например, 2^ -1), возникает ошибка типа, а затем появляются другие ошибки для сложных или неопределенных результатов.

(^)/2 довольно долго использовался для возведения в степень. Раннее использование оператора возведения в степень находится в D.H.D. Тезис Уоррена 1977 года на примере символической дифференциации. (Это по крайней мере не упомянуто в руководстве Филиппа Русселя 1975 года). На протяжении всей диссертации и руководства пользователя 1978 года символ ~ используется последовательно там, где можно ожидать ^ как в integers are restricted to the range -2~17 to 2~17-1 , ie. -131072 to 131071. Объявление было следующим и не изменилось с 1982 года.

:- op(300, xfy, ~).  % 1977
:- op(200, xfy, ^).  % 1982 - today

С 1982 года он использовался для количественного определения setof/3 и bagof/3 но также как лямбды в парсерах естественного языка. Для всех этих применений у него уже была правильная ассоциативность и приоритет. Как оцениваемый функтор, он присутствовал в нескольких системах.

Первая система, которая использовала (^)/2 в качестве оцениваемого функтора, означающего мощность, вероятно, C-Prolog.

По сравнению с этим наследием, (**)/2 появился в Прологе относительно поздно, скорее всего, вдохновленный Фортраном. Он был предложен для включения (N80 1991-07, парижские документы) незадолго до первого проекта Комитета (CD 1992). Системы предоставили это также как exp/2.

(**)/2 имеет тот же приоритет, что и (^)/2 но не имеет никакой ассоциативности, которая на первый взгляд может показаться странной, поскольку в некоторых случаях довольно часто возводить в степень дважды. Наиболее заметно, что гауссовская функция в ее простейшем виде

  

е -x 2

Вместо использования константы e и возведения в степень предусмотрен специальный оцениваемый функтор exp/1. Таким образом, выше написано как exp(- X**2). На самом деле, также Википедия использует эту запись. Учитывая этот функтор, в этом общем случае нет необходимости в ассоциативности.

Если он действительно будет, мне было бы очень интересно его увидеть.

По сравнению с другими системами довольно распространено предложение двух видов возведения в степень. Подумайте о Haskell, в котором есть ^ и ** .

В заключение: не часто встречается случай, когда требуется возведение в степень вложенного числа с плавающей точкой. Так что минимальная поддержка кажется предпочтительной.

ответил false 11 ThuEurope/Moscow2014-12-11T04:52:22+03:00Europe/Moscow12bEurope/MoscowThu, 11 Dec 2014 04:52:22 +0300 2014, 04:52:22
0

@false ответил на ваш первый вопрос.

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

?- integer(-1).
true.

?- X = 1, integer(-X).
false.

и следующие приоритеты:

?- current_op(X, xfx, **).
X = 200.

?- current_op(X, fy, -).
X = 200.
ответил mat 11 ThuEurope/Moscow2014-12-11T09:51:45+03:00Europe/Moscow12bEurope/MoscowThu, 11 Dec 2014 09:51:45 +0300 2014, 09:51:45
0

Причина (не оправдание) несоответствия заключается в том, что в исходном стандарте 1995 года только **/2 был оператором арифметического возведения в степень, тогда как ^/2 использовался только для количественного определения переменных в bagof/3 и setof/3. Для последнего использования имело смысл иметь право-ассоциативность, чтобы вы могли написать X^Y^foo(X,Y,Z). Почему **/2 не было присвоено xfy ассоциативности я не знаю (это было бы согласованно с Фортраном, например).

^/2 как оператор возведения в степень был добавлен в «исправление» 2012 года без изменения синтаксиса, что привело к текущей несогласованности.

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

:- op(200, xfy, **).

Это вряд ли вызовет какие-либо проблемы. Более того, во многих современных объявлениях операторов Prologs действуют только локально в модуле.

ответил jschimpf 11 ThuEurope/Moscow2014-12-11T01:55:29+03:00Europe/Moscow12bEurope/MoscowThu, 11 Dec 2014 01:55:29 +0300 2014, 01:55:29

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132