Исключения и восстановление после ошибок

Ivan8209

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

try ( чего-то ) recover ( сюда, если ошибка ) endtry

2. Тульский

try ( чего-то ) finally ( сюда ) end-try
try ( чего-то ) except ( сюда, если ошибка ) end-try

А теперь вопрос.
Что привычнее насильникам?
Ну, или другим программистам, не обладающим
большим опытом общения с системой без "try".
Вопрос не праздный, ибо от этого зависит объём работ,
столько документации на аглицком я не напишу.
Можно предложить свой синтаксис, я подумаю,
если будет удобно, могу взять на вооружение.
---
VARIABLE 1

Papazyan

Монопенисуально. В С++ используется catch для ошибок. finally тоже есть, но под Виндами.

psihodog

в java 2-е.
в питоне 2-е + ещё else есть.

Ivan8209

По тульскому способу можно писать

try ( что-то ) except ( ошибка ) else ( обычно ) end-try

Ты это имеешь в виду?
---
VARIABLE 1

psihodog

да, это.
просто, у тебя там явно не написано, что есть else.

Ivan8209

А оно сделано немного грязным хаком (хотя... это вопрос стиля поэтому я про него забыл.
Просто end-try проверяет, было ли там if, зашитое в except, и вставляет недостающий then.
---
VARIABLE 1

bleyman

насильникам привычно вот так (это шарп, но в плюсах почти так же):

     try
     {
     Console.WriteLine("Executing the try statement.");
     throw new NullReferenceException;
     }
     catch (NullReferenceException e)
     {
     Console.WriteLine("{0} Caught exception ", e);
     }
     catch
     {
     Console.WriteLine("Caught exception ");
     }
     finally
     {
     Console.WriteLine("Executing finally block.");
     }

Executing the try statement.
System.NullReferenceException: Object reference not set to an instance of an object.
   at EHClass.Main Caught exception Executing finally block.

finally и else (тут - catch без параметров) это всё-таки разные вещи.

psihodog

else (тут - catch без параметров)
что такое по-твоему else? т.е. когда должен выполняться код из блока else?

Ivan8209

То есть,

:noname
try ." try" cr 2 throw recover
case
1 of ." exc#1" cr endof
2 of ." exc#2" cr endof
throw ( unknown )
endcase
." finally" cr
endtry
; cr execute


try
excfinally
ok

Так?
Слово "catch" я занять не могу --- ANS X3.215--1994 9.6.1.0875,
но могу придумать грязный хак, чтобы спрятать case/endcase.
Что-то вроде

try ... catches ... of ... endof ... finally' ... end-try'

---
VARIABLE 1

bleyman

Когда исключение не удовлетворяет ни одному из условий в catch-ах.
А finally выполняется всегда.

Andbar

вообще-то мне казалось, что else в питоне выполняется в том случае, когда исключения вообще не возникали. Или я ошибаюсь?

Ivan8209

Чего-то у вас уже пошли разногласия.
Судя по всему, в довесок к try/recover/endtry или try/finally/end-try ничего не надо,
няхай каждый сам, как умеет разбирает, как его кинули.
---
...Я работаю антинаучным аферистом...

bleyman

Что-то у тебя много лишних слов появляется из-за отсутсвия операторных скобок.
Я б вот так сделал (это больше на паскаль похоже, правда)
  
:noname
try
." try" cr 2 throw
catchcase 1 ." exc#1" cr
catchcase 2 ." exc#2" cr
catchany throw
finally ." finally" cr
endtry
; cr execute

после слова catchcase всегда идёт ровно одно слово - условие (так же можно сделать? а потом обработчик
С возможностью опускать catchcase, catchany (в таком случае неявно подставляется catchany throw) и finally. И проверять, что catchany всегда последнее и не более одного.
Единственный недостаток - не получится просто так делать вложенные блоки, что лечится добавлением слова endcatch, но тут сам думай, оправдано ли это.

bleyman

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

psihodog

именно так.

psihodog

Но сишная схема, кажется, описывает все возможные потребности:
как ты уже мог догадаться, она не описывает потребность:
* кусок исполняющийся при отсутствии исключений

Marinavo_0507

> кусок исполняющийся при отсутствии исключений
в конец блока этот кусок запихни, и всё

Ivan8209

> после слова catchcase всегда идёт ровно одно слово -
> условие (так же можно сделать? а потом обработчик
Сделать можно, но это не очень хорошо.
Парсящие слова, всё же, для другого придуманы.
Преимущество того, что есть зазор между recover и case,
заключается в том, что можно поправить то, что кинули.
Например, объединить арифметическое переполнение с чем-нибудь твоим,
чтобы было одно "неправильный формат данных."
Это же можно сделать, если вместо case/endcase использовать что-нибудь другое.
Например, cond/thens.
Не очень понятно, зачем у тебя есть finally.
Это можно вообще вынести за пределы try/endtry и выкинуть лишнее слово полностью.
Чё-то, по-моему, у тебя фигня какая-то получается.
Не нравится оно мне очень.
Там же ещё надо вхакать в catchcase и catchany что-то,
что при первом появлении будет ставить "; >resolve literal catch",
а при всех остальных --- не ставить.
А если допустить, что может не быть их обоих,
то это же надо произвести и с finally.
Не, не нравится мне это.
Очень не нравится.
---
VARIABLE 1

psihodog

в конец блока этот кусок запихни, и всё
это не то же самое
кроме того, мне кажется, что с так активно пропагандируемой питоном идеологией EAFP (помните, что легче потушить пожар, чем всё время его предотвращать иногда логично написать код в else даже когда это не обязательно. Хотя, возможно, здесь я не прав.
PS Кстати, в питоне, else есть ещё и у оператора for — тоже очень удобная вещь.

Andbar

PS Кстати, в питоне, else есть ещё и у оператора for — тоже очень удобная вещь.
Ага, это одна из вещей, которые мне очень понравились в Питоне. Достаёт иногда лишнюю проверку после цикла писать.

Ivan8209

Любители править задним числом...
> PS Кстати, в питоне, else есть ещё и у оператора for — тоже очень удобная вещь.
Это как?
---
...Я работаю антинаучным аферистом...

qsk78

Ветка else срабатывает, если цикл выполнился полностью, т. е. не было прерывания цикла с помощью break'а.

Ivan8209

Не вижу никакой пользы от этой примочки.
У этих си-подобных циклов основная проблема в том,
что условие можно проверить только в начале,
из-за чего и появляется "break".
---
...Я работаю антинаучным аферистом...

psihodog

У этих си-подобных циклов основная проблема в том,
что условие можно проверить только в начале,
из-за чего и появляется "break".
в питоне не си-подобный цикл.
в питоне, он shell-подобный, т.е.:
for i in smth: ...
а какие ещё бывают варианты, кроме С и sh?
Не вижу никакой пользы от этой примочки.
Этой фишки очень часто мне не хватало в Java/C/++, когда после выхода из цикла нужно было знать, как он закончился: по бреку или по невыполнению условия. Вместо этого приходилось писать что-нть вроде:
int i;
for (i= 0; i<n; ++i) {
   ...
}
if (i==n) {
   ...
}

что несколько непонятнее и некрасивей, чем:
for (int i= 0; i<n; ++i) {
   ...
} else {
   ...
}

(+ещё переменная во внешнем скопе и лишнее сравнение)

Dasar

Этой фишки очень часто мне не хватало в Java/C/++, когда после выхода из цикла нужно было знать, как он закончился: по бреку или по невыполнению условия. Вместо этого приходилось писать что-нть вроде:
Задача какая решается этим for-ом?
последовательный поиск?

psihodog

ну что-нть вроде этого...
хотя, конечно, всех использований for else я не помню...
ну, например вот так:
for (i= 0; i<n; ++i) {
...
if (item[i].mathces(condition break;
...
}
if (i==n) {
throw new NotFound(item, condition);
}

Dasar

имхо, лучше в язык вводить объявление "функции" внутри функций, чем такие извраты, как for else

if (!Contains(items, delegate (Item item){return item.matches(condition);})
throw new NotFound(item, condition);

for else закрывает только одну из локальных задач (а именно последовательный поиск при этом являясь довольно нелогичным по семантике

psihodog

if (!Contains(items, delegate (Item item){return item.matches(condition);})
throw new NotFound(item, condition);
ну, во-первых, одно другому не мешает.
а во-вторых, ты не заметли многоточий в моём коде перед вызовом matches? их ты куда дел?
for else закрывает только одну из локальных задач (а именно последовательный поиск)
почему только одну?
при этом являясь довольно нелогичным по семантике
очень даже логичным, если смотриеть на фор под таким углом:
label:
if (condition) {
do something;
do increment;
goto label;
} else {
do else;
}

Ivan8209

> в питоне не си-подобный цикл.
> в питоне, он shell-подобный, т.е.:
> for i in smth: ...
Хрен редьки не слаще.
Какой смысл раннего выхода из вот этого цикла,
если smth представляет собой однородный список,
как это задумывалось при проектировании?
> а какие ещё бывают варианты, кроме С и sh?
Есть варианты вообще без циклов.

begin cond-1? while cond-2? while repeat not-cond-2 else not-cond-1 then
begin cond-1? while cond-2? until cond-2 else not-cond-1 then

В любом месте можно производить дополнительные действия,
везде можно выкинуть else и соответствующую последовательность до then.
Есть ещё страшный способ с do-while-loop-else-unloop-then,
но я его не использую и не задумываюсь об этом.
Весь прикол заключается в том, что всё это на самом деле всего три конструкции:
а) бесконечный цикл begin-again;
б) цикл со счётчиком do-loop;
в) условное выражение if-else-then.
Просто while --- это такой if, подправленный так,
чтобы перекрывались цикл и условное выражение.
("repeat" --- это просто "again then")
---
VARIABLE 1

Dasar

> очень даже логичным, если смотриеть на фор под таким углом:
мне не нравиться, что эта семантика подразумевается не явно.
имхо, семантика должна явно читаться из синтаксиса.
в данном случае, семантика получается:
для всех элементов проверить условие, если условие всегда выполнялось, то выполнить то-то (то что после else)
вот именно это и хочеться в коде увидеть:
if (CheckAll(items, condition
then ...

psihodog

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

psihodog

begin cond-1? while cond-2? while repeat not-cond-2 else not-cond-1 then
begin cond-1? while cond-2? until cond-2 else not-cond-1 then
боже, что это?

Ivan8209

"Расширь своё сознание!"
---
"Потому что Аллах не ведёт людей неверных."

psihodog

"Расширь своё сознание!"
Пропагандируешь наркотики?
Куда копать хотя бы?

Ivan8209

Копать хотя бы тот же ANS X3.215--1994.
Ибо сказано в Писании (A.3.2.3.2.)

The basic control structures can be supplemented, as shown in
the examples in figure A.3, with additional WHILEs in BEGIN ...
UNTIL and BEGIN ... WHILE ... REPEAT structures. However, for
each additional WHILE there must be a THEN at the end of the
structure. THEN completes the syntax with WHILE and indicates
where to continue execution when the WHILE transfers control.
The use of more than one additional WHILE is possible but not
common. Note that if the user finds this use of THEN
undesirable, an alias with a more likable name could be defined.

---
"Аллах не ведёт людей неверных."

Ivan8209

Да, спасибо, хорошая статья. Стоило посмотреть.
Единственное, что, мой вопрос более связан с синтаксисом
и семантикой операций, а не с механизмом реализации.
Основной вопрос на сейчас ставится так:
насколько важно отделять исключительные случаи?
Поясню.
В самом простом случае важно указать одну точку,
куда надо в исключительных обстоятельствах свалиться сразу.
То есть, вообще говоря, достаточно сделать конструкцию "try ... finally",
после которой разбирать, что же у нас там приключилось,
не случилось ли чего странного по пути.
В самом простом случае, оно выглядит так

try ... finally ?dup if ." Что-то случилось этой весною..." cr then

После "finally" почти наверняка пойдёт какая-то условная конструкция.
Соответственно, можно срастить имеещееся "finally" с тем, что отграничивает разбор условий.
Например, если срастить "finally" с "?dup if", получим описанный выше "except".
А кроме "if" ещё туда можно поставить
а) "case ... of ... endof ... endcase" (это урезаный паскалевский "case");
б) "cond ... thens" (это "if...elseif...else...endif");
в) "case: ... ;end" (это, если надо, я потом объясню);
г) что-нибудь страшное, связанное, например,
с поиском по ассоциативному списку.
А ведь ещё можно засечь место, где было "try"
и предоставить возможность повторять попытки:

begin try ... end-try while ... repeat

Срастить правильно слова и всё это сделать одной большой конструкцией.
Чтобы жизнь мёдом не казалась.
---
...Я работаю антинаучным аферистом...
Оставить комментарий
Имя или ник:
Комментарий: