Здравствуйте, AlexRK, Вы писали:
ARK>А можно через монады организовать, например, циклы? Чисто гипотетически, конечно, но все равно: сперва "открыть", потом произвольное количество раз сначала "читать", потом "писать", и в самом конце "закрыть".
Ну, такое-то можно и без монад.
Достаточно сильная система типов отличает "новый сокет" от "открытого сокета" и от "закрытого сокета". Поэтому достаточно объявить правильные сигнатуры у функций открытия/чтения/закрытия.
ARK>Ну да, этого недостаточно. Я, кстати, не могу придумать нормального варианта, как быть в такой ситуации, то бишь если происходит крах при финализации. Похоже, единственное, что можно сделать — как-то передать ошибку наверх. Но при этом должны выполниться и все остальные деструкторы. Правда, ошибка в первом деструкторе может повлиять и на остальные... В общем, хз, как лучше. Конечно, лучше всего статически запретить любые ошибки в финализаторах, но это не сработает для внешних сущностей — баз данных, сетевых соединений и т.п.
Надо понять,
1. Что мы хотим делать в случае возникновения ошибки на таком этапе. Если вообще отвлечься от деструкторов, финализаторов, скоупов, и исключений. Вот мы писали-писали данные в буфер, вот стали сохранять — облом, кончилось место на диске. Что мы будем делать? Пытаться повторно? Откатывать назад к "предыдущему успешному чекпоинту"?
2. Отличается ли стратегия завершения для успеха и неудачи. Предположим, в процессе подготовки данных для записи в файл мы напоролись на деление на ноль. Имеет ли смысл вообще пытаться записывать кусок буфера? Или надо откатываться к "предыдущему успешному чекпоинту"? Или можно просто бросить как есть, т.к. упорно пытаться записывать мусор бессмысленно, а откатывать назад — дорого.
Пока что выглядит всё так, что даже пытаться делать commit стоит только при условии выхода из блока без исключений. При исключительном выходе нужно применять либо rollback, либо ignore.
Дальше начинаются нюансы — что, если у нас три файла, выходим успешно, один уже закоммитился, теперь коммитим второй — упс, ошибка. Очевидное решение (скорее всего неверное) — продолжать отмотку с учётом изменившейся ситуации. То есть для второго и третьего мы попробуем теперь вызвать "завершатель ошибки".
В таком подходе можно попытаться запретить (языком и верификацией) выброс исключений из fault completion handler, разрешая нетривиальную логику в success completion handler.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.