Киньте без подвоха в ISO Пролог

Я борюсь с точной семантикой throw/1 без подходящего catch/3 в ISO Prolog. Я читаю спецификацию ISO Prolog, и мне кажется, что выполнение закончится бесконечной рекурсией.

(Обратите внимание, что для интерпретации этого вопроса у вас должен быть доступ к стандарту ISO Prolog).

Шаг 1. Допустим, мы вызываем throw(unknown), и в стеке нет catch/3.

Шаг 2. Это закончится в 7.8.10.1 c), сказав, что это будет системная ошибка (7.12.2 j).

Шаг 3. Это такая же формулировка, которая используется в других местах для других мест, поэтому я предполагаю, что она должна интерпретироваться таким же образом. Поэтому применяется 7.12.1, и текущая цель (throw/1) будет заменена throw(error(system_error, Imp_def)).

Шаг 4. Выполнение этой цели не найдет для нее активного "улова" в стеке. Поэтому он должен попытаться выполнить те же шаги, продолжить на шаге 2 и т. Д. => Бесконечная рекурсия.

Вы можете сказать, что преобразование необработанного "throw" в system_error является "final" и не подлежит дальнейшей обработке, как другие ошибки, и, вероятно, должно быть так, чтобы избежать описанной мной проблемы, но мой вопрос Где в стандарте это покрыто?

Некоторые другие заметки, для полноты:

  1. В примечании 4 в 7.12.2 также упоминается возможность системной ошибки при этих обстоятельствах. Я думаю, что используемая там формулировка ("... нет активной цели" /3") вводит некоторую путаницу в еще один аспект, поскольку она должна квалифицировать это с условием, что Catcher должен объединиться с термином ошибки (B).

  2. Какова идея преобразования неперехваченных бросков в системную ошибку? Похоже, что он может существовать, чтобы облегчить жизнь для верхнего уровня процессора Prolog, чтобы он получал только одну предсказуемую ошибку? Для меня это приносит больше проблем, чем выгод - истинная причина ошибки, таким образом, исчезнет - любое мнение или комментарий?

  3. Формальная семантика (Приложение A), похоже, тоже как-то борется с этим, хотя я не изучал это до мелочей. В A.2.5 упоминается, что "... Однако в формальной спецификации есть ловушка в корне...", и связывает это, например, с выполнением findall/3. Так формальная спецификация здесь отличается от основного текста?

1 ответ

Решение

(Мы говорим здесь о ISO/IEC 13211-1:1995)

Определение контрольной конструкции throw/1 (7.8.10) утверждает в двух местах, что в этой ситуации должна быть системная ошибка. Во-первых, как вы заметили, есть 7.8.10.1 c:

c) Должна быть системная ошибка (7.12.2 j), если S сейчас
пусто,

и затем есть предложение об ошибке:

7.8.10.3 Ошибки

а) B переменная
- instantiation_error,

б) B не объединяется с C аргумент любого вызова
улова /3
- system_error,

Чтобы увидеть, что такое системная ошибка, нам нужно взглянуть на подпункт 7.12.2 j:

j) На любой стадии
выполнение. Условия, при которых должно быть
системная ошибка и действия, предпринятые процессором после
системная ошибка зависит от реализации. Имеет
форма system_error,

Таким образом, действие, предпринимаемое процессором после системной ошибки, зависит от реализации. Бесконечный цикл тоже подойдет.

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

Объявление 1: Примечание не является нормативным. Смотрите 1.1 Примечания. Это по сути резюме.

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

Примечание 3: формальная семантика - это, по сути, другая реализация. А в некоторых частях реализация должна принимать определенные решения, тогда как спецификация может оставить открытыми все возможности. Кроме того, обратите внимание, что формальная семантика не является нормативной. Тем не менее, это помогло отладить стандарт.

Изменить: В комментариях вы говорите:

(1 месяц) То есть вы говорите, что это позволяет процессору немедленно выполнять зависящее от реализации действие при возникновении системной ошибки, а не только после ее устранения? (2do) Таким образом, освобождая его от необходимости применять трансформацию цели в 7.12.1? (3tio) Тогда было бы также нормально, если бы системные ошибки не могли быть отслежены (catch/3) вообще?

1MO

Предложение в 7.12.2 j

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

эффективно отменяет 7.12.1. Аналогично 7.12.2 ч, что может произойти "на любой стадии исполнения".

Просто чтобы быть уверенным, что мы читаем кодекс, на мгновение предположим обратное. Представьте, что произошла системная ошибка, и теперь 7.12.1 выдаст такую ​​ошибку, которая нигде не будет обнаружена, тогда у нас снова будет системная ошибка и т. Д. Таким образом: приведенное выше предложение никогда не будет применяться. Уже одно это говорит о том, что мы прочитали здесь что-то неправильно.

С другой стороны, представьте ситуацию, когда системная ошибка возникает, когда система полностью повреждена. Как теперь должен быть выполнен 7.12.1? Таким образом, система Prolog не сможет выполнить этот цикл. Означает ли это, что процессор Prolog может соответствовать, только если мы сможем доказать, что системной ошибки никогда не будет? Это практически невозможно, в частности, потому что

7.12.2 Классификация ошибок

ЗАМЕТКИ

...
4 Системная ошибка может произойти, например, (а) во взаимодействиях
с операционной системой (например, сбой или прерывание диска),
...

Так эффективно это будет означать, что не может быть никакого соответствующего процессора Prolog.

2do

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

3tio

Краткий ответ: да. Это довольно экстремально, но верно, считая, что системные ошибки не поддаются отслеживанию, и тогда выполнение будет прервано. Но, возможно, сначала сделайте шаг назад, чтобы понять (а) для чего нужен технический стандарт, а что нет, (б) область применения стандарта.

Объем

Или, скорее, начните с b: в 1 Scope мы имеем:

ПРИМЕЧАНИЕ. - Эта часть ISO / IEC 13211 не определяет:

...
f) пользовательская среда (цикл верхнего уровня, отладчик, библиотека
система, редактор, компилятор и т. д.) процессора Prolog.

(Строго говоря, это всего лишь примечание, но если вы пролистаете стандарт, вы поймете, что эти аспекты не указаны.) Я несколько подозреваю, что на самом деле вы хотите понять, что цикл верхнего уровня должен делать с необработанной ошибкой. Однако этот вопрос выходит за рамки 13211-1. Вероятно, имеет смысл сообщить о такой ошибке и продолжить выполнение.

Цель

Другой момент здесь - то, для чего фактически нужен технический стандарт. Технические стандарты часто неправильно понимают как полную гарантию того, что система будет работать "должным образом". Однако, если система соответствует техническому стандарту, это не означает, что она пригодна для каких-либо целей или использования. Чтобы показать вам самое крайнее, рассмотрим команду оболочки exit 1 который может рассматриваться как процессор, соответствующий стандарту 13211-1 (при условии, что он сопровождается документацией, которая определяет все функции, определенные реализацией). Зачем? Хорошо, когда система запускается, она может понять, что минимальные требования (1 Область, Примечание b) не выполнены, и, таким образом, она вызывает системную ошибку, которая обрабатывается путем создания кода ошибки 1.

То, что вы на самом деле хотите, - это скорее система, которая соответствует и подходит для определенных целей (которые выходят за рамки 13211-1). Поэтому, помимо того, что вы спрашиваете себя, соответствует ли определенное поведение или нет, вы также узнаете, как эта система подходит для определенных целей.

Хорошим примером для этого являются ошибки ресурсов. Многие системы Prolog способны обрабатывать определенные ошибки ресурсов. Рассматривать:

p(-X) :- p(X).

и запрос catch(p(X),error(E,_),true). У системы теперь есть несколько возможностей: бесконечный цикл (который требует очень, очень умного GC), успех с E = resource_error(Resource), преуспеть с E = system_error, остановите выполнение с некоторым кодом ошибки, съедите все ресурсы.

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

Точно так же в случае system_errorЕсли это имеет смысл, было бы хорошей идеей правильно сообщать о системных ошибках в Prolog, однако, если дела зашли слишком далеко, спасение от кризиса все еще не самое худшее, что может произойти. На самом деле, наихудшим (но все еще соответствующим) способом было бы продолжить выполнение "как будто", все хорошо, когда это не так.

Другие вопросы по тегам