Здравствуйте, s22, Вы писали:
s22>Здравствуйте, VladD2, Вы писали:
VD>>И, вообще, чем они свои экстравагантные поступки то объясняют? Без ЖЦ все плохо?
s22>try catch относят к плохому стилю написания, как и goto s22>например на форуме gcc жаловались на то, что использование исключений серьезные создает проблемы с оптимизацией кода.
try catch — да, плохой стиль.
Правильный exception-safe код никаких try catch не содержит, все делается через RAII.
Здравствуйте, artelk, Вы писали:
C>>В Rust — невозможно. A>Т.е. исключение (потенциально бросаемое из функции) является частью сигнатуры этой функции? Чем это по сути отличается от явовских чекед исключений, от которых почти все плюются?
Да. От Java-вских исключений плюются по причине неудобности их использования, а сама идея очень здравая.
Здравствуйте, VladD2, Вы писали:
VD>>>Что такое DWARF maps? C>>Табличная обработка исключений, когда адрес обработчика указан для каждого места, где может возникнуть исключение. VD>Об этом где-то можно почитать? http://mortoray.com/2013/09/12/the-true-cost-of-zero-cost-exceptions/
VD>И вообще, какие аргументы против исключений, кроме того, что в С++ они не продуманы?
Сложность корректного unwinding'а.
VD>Без исключений ты должен будешь делать массу не относящихся к основному алгоритму проверок или засорять код опертором "?.", который в данном случае можно назвать "отвяжись".
Ага. Только это делается явно.
VD>Что является еще одной обузой. Прикинь, что будет с кодом, если в функции попарсить числа из строк, сходить в БД и т.п.? А что будет в тех функциях которые вызывают такие функции? VD>Получаются те же исключения, но которые постоянно заставляют программиста "приседать". Плюс производительность они просаживают не только в месте где try/catch/finally написан, а в любом месте вызова функции обрабатывающей ошибки.
Ну а что тогда делать, если уровнем выше надо проверить не упало ли всё из-за базы данных и в этом случае сделать failover на другой источник данных? Откуда ты узнаешь какой именно тип исключения и не изменит ли его завтра автор на обёрнутое исключение?
VD>Ну, как не страдает, когда почти все "фичи" — это попытка делать современный язык без GC. На фиг тогда нужны все эти явные времена жизни, ARC, отказ от исключений?
Это попытка сделать надёжный язык.
VD>Вот есть у меня функция, которая внутри которой получается строка, парсится как число и число дальше используется для вычислений. Эта функция вызвана через 100500 функций и в итоге я должен вывести пользователю (предположим, на консоль) результат вычислений. С исключениями я тупо реализую алгоритм. Если во входной строке не число, то в самом коре вызовов я перехвачу все исключения и выведу на консоль текст из исключения.
А теперь представь, что ты пишешь код файловой системы и при размотке стека тебе надо вернуть на место все изменения.
VD>При явной обработке ошибок я буду вынужден забить все возвращаемые значения сообщениями об ошибках. И еще по пресидать, чтобы обеспечить их совестимость и правильное протаскивание вниз.
Всё правильно. Иначе будет вариант, что пользователь рядом с полем ввода увидит сообщение "Failed to read /usr/share/tzinfo".
VD>Сейчас в MS VS одна из основных проблем — это куча COM-овского кода который вместо нормальной обработки ошибок тупо возвращает E_FAIL и причину ты уже не узнаешь никогда, если ты не знаком с кем-то из МС и он не посмотрит в исходниках.
В Rust возвращается типобезопасная ошибка, с возможностью запомнить её stack trace.
VD>Это распространение очередной надумано догмы. Давай ты мне покажешь обсуждение проблемы вызванной try/... в том же C#-е.
class CompoundRecord
{
private final FileInputStream stream1, stream2;
public CompoundRecord(String fname1, String fname2) {
stream1 = new FileInputStream(fname1);
try {
stream2 = new FileInputStream(fname2);
} finally {
stream1.close();
}
}
public void close()
{
stream1.close(); //А что если тут исключение будет?
stream2.close();
}
};
Здравствуйте, Cyberax, Вы писали:
C>А теперь представь, что ты пишешь код файловой системы и при размотке стека тебе надо вернуть на место все изменения.
Тебе транзакции нужны здесь. Исключения из другой оперы.
Здравствуйте, Cyberax, Вы писали:
C>Исключения можно забыть обработать (что бывает сплошь и рядом) — это основная причина отказа от них в Rust.
Это прекрасно! Отлично!
Я просто счастлив, из-за того, что оно так и есть, потому что: код возврата тоже можно забыть проверить, но ведёт это к куда более печальным последствиям, чем необработанное исключение, а всё потому, что искать ошибку в данных, ломая голову о причинах пересчёта погоды в Африке, куда хуже чем упавшая софтина, которая к тому же оставила стэк-трэйс в логе.
Фикус тут в том, что ловить и обрабатывать исключения нужно тогда, когда ты точно знаешь что ловить и как это обрабатывать, а иначе — пусть падает.
Всё сказанное выше — личное мнение, если не указано обратное.
Здравствуйте, Философ, Вы писали:
C>>Исключения можно забыть обработать (что бывает сплошь и рядом) — это основная причина отказа от них в Rust. Ф>Это прекрасно! Отлично! Ф>Я просто счастлив, из-за того, что оно так и есть, потому что: код возврата тоже можно забыть проверить
В Rust нельзя забыть проверить код возврата.
Здравствуйте, Cyberax, Вы писали:
C>В Rust нельзя забыть проверить код возврата.
Да ладно?
let x = fooWhichReturnError();
x?.Bar();
return 42;
И еще ладно бы забыть случайно или намеренно! Но в жизни же бывают случаи, кода ты будешь вынужден "забыть" свои коды. Вот нужно тебе реализовать интерфейс не предусматривающий код возврата, но при его реализации ты вынужден вызвать функции с кодами возврата. Что делать? Только "забыть".
Или интерфейс предусматривает один код, а функции возвращают другие коды. Значит мы сидим и препаковываем. И это еще в лучшем случае, так как исходный код может не позволять сохранить данные из полученного.
Короче, тупиковый путь. И к чему он ведет отлично видно по COM-у. Там просто возвращают если что универсальный E_FAIL и понять реальную причину невозможно.
Далее отладка. Так я включаю перехват исключений и вижу место возникновения ошибки. С кодами возврата так не выйдет. Это же ординарный код.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>И еще ладно бы забыть случайно или намеренно! Но в жизни же бывают случаи, кода ты будешь вынужден "забыть" свои коды. Вот нужно тебе реализовать интерфейс не предусматривающий код возврата, но при его реализации ты вынужден вызвать функции с кодами возврата. Что делать? Только "забыть".
Подозреваю, что будет практиковаться дописывание "throws Exception" ко всем сигнатурам методов. Следующим шагом объявят это дописывание поведением по умолчанию и поручат компилятору. Вышеприведенный "Error(e) => return Error(e);" будет также по умолчанию вставлятся везде, где явно не будет написан catch (или его растовый аналог). Потом сделают сохранение информации о стеке вызовов. Короче, переизобретут обычные исключения.
Здравствуйте, artelk, Вы писали:
C>>В Rust нельзя забыть проверить код возврата. A>А если функция "возвращает" void? Будет ли компилятор заставлять мачтить Result<void, Error>?
К.О. подсказывает, что если функция возвращает void, то она не может возвращать код ошибки.
Здравствуйте, VladD2, Вы писали:
VD>let x = fooWhichReturnError(); VD>x?.Bar();
Тут явно пробрасывается исключение.
VD>Далее отладка. Так я включаю перехват исключений и вижу место возникновения ошибки. С кодами возврата так не выйдет. Это же ординарный код.
В Error запоминается место создания, не проблема.
Здравствуйте, VladD2, Вы писали:
VD>Кстати, в D есть проблемы с исключениями в деструкторах?
Еще какие! Деструктор же нередко вызывается сборщиком мусора, а в этот момент низя выделять память в егойной куче, поэтому "new Exception" вызывает кирдык — вылет с InvalidMemoryOperationError.