- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 10
- 11
- 12
- 13
- 14
- 15
private Action<Action, Action<Exception>> ToCallbackAction(Action a)
{
return (sc, ec) =>
{
try
{
a();
sc();
}
catch (Exception e)
{
ec(e);
}
};
}
tirinox 01.04.2014 16:59 # +3
wvxvw 01.04.2014 19:43 # 0
Назначение ошибок, ну, по крайней мере изначально, было в том, чтобы получить какой-то контроль над процессом выполнения програмы, ну а тут он не нужен...
neeedle 02.04.2014 09:05 # 0
Сама идея интересна.
wvxvw 02.04.2014 09:22 # 0
neeedle 02.04.2014 18:37 # 0
тем более throw тут нигде нет, стек вызовов в ошибке остался.
Я вижу тут очень интересный делегат.
Хотя применения ему найти трудно.
wvxvw 02.04.2014 19:07 # 0
neeedle 02.04.2014 19:28 # 0
Там нет никакого результата.
wvxvw 02.04.2014 19:40 # 0
bormand 02.04.2014 19:45 # 0
Все-таки ошибка (исключительная ситуация) это не когда функция не может вернуть объект нужного типа, а всего лишь когда она не справляется со своими обязанностями (нарушены какие-то предусловия, или вызываемая ей функция выбросила ошибку или что-то еще).
wvxvw 02.04.2014 20:11 # 0
Не нужно спрашивать: "а что возвращать" - такого ворпоса не должно быть изначально. А зачем нужно было функцию писать, если она ничего не возвращает? Тип ошибки - это часть типа функции, но тип "ничего" объединенный с типом "ошибка" - это маразм.
Просто у ошибки есть специфический побочный эффект - размотка стека ради которого, и только ради него имеет смысл пользоваться ошибками. Если отматывать стек не нужно - то нефиг и ошибку выбрасывать (другими словами, ситуацию можно разрулить на месте).
bormand 02.04.2014 20:26 # 0
Ну да, и я с ним согласен. Но в c# это обернуто в синтаксический сахар, называемый исключениями. И переть в обход системы где-то возвращая исключения самому, а где-то юзая встроенный механизм - какой-то изврат.
> А зачем нужно было функцию писать, если она ничего не возвращает?
Ну не на хаскеле же пишем :) Ради побочных эффектов, вестимо.
> Тип ошибки - это часть типа функции, но тип "ничего" объединенный с типом "ошибка" - это маразм.
Это не маразм. Маразм - это "тип" void, не имеющий ни одного значения. Был бы он типом, принимающим единственное значение void (так называемый unit type) - вы бы до пары (void, Exception) уже бы никогда не докопались ;))
> Просто у ошибки есть специфический побочный эффект - размотка стека ради которого, и только ради него имеет смысл пользоваться ошибками.
Т.е. если я пишу функцию ради побочного эффекта, то я должен ПОЙМАТЬ ошибку и ВЕРНУТЬ ее как результат? Ну очень удобно... Это как раз таки убьет всю пользу от исключений.
wvxvw 02.04.2014 21:02 # 0
Это ж идиотизм. Хотя, вобщем-то, да, распространенный. Т.е. вместо того, чтобы открыть файл и вернуть на него ссылку мы потом по косвенным признакам догадываемся о том, что файл все-таки открылся, а возвращаемое значение игнорим.
bormand 02.04.2014 21:29 # 0
Так что проблема совсем не в том, что функции могут вернуть ничего.
wvxvw 02.04.2014 21:46 # 0
bormand 02.04.2014 21:55 # 0
Ну дык здесь уже на уровне языка и рантайма есть неявное логическое значение... Это тот самый флаг-селектор в объединении возвращаемого типа и типа ошибки. Функция вернула управление с помощью return - true, вернула управление с помощью throw - false.
Можно подумать, что кому-то хочется обрабатывать возвращаемое значение каждого print'а по-отдельности...
Собственно в этом и основное удобство исключений - за счет "магии" компилятора и рантайма человеку не надо вставлять проверку успеха\неуспеха после вызова каждой функции. Флаг успеха\неудачи сделан неявным (на самом деле там более хитрые механизмы, но это неважно, поведение один хрен точно такое же, как-будто каждая функция возвращает Either<ReturnType, ExceptionType>) и неудачи автоматом возвращаются на уровень выше, если их не хотят обрабатывать в текущей функции.
wvxvw 02.04.2014 22:01 # 0
Ну так а где в примере обработка множества ошибок? Ее ж там нет. Более того, ее и не сделаешь особо полезной, т.как полиморфизьм в try-catch не особо работает.
bormand 02.04.2014 22:04 # 0
В котором примере?
> return true не задействует ненужного в данном случае механизма манипуляции стеком
Зато он добавляет кучу бесполезных проверок в success path. А это - преждевременная пессимизация ;)
В том же g++ исключения вообще не добавляют стоимости к успешной ветке. Там за них платят только при возникшей ошибке, что, имхо, вполне логично.
> полиморфизьм в try-catch не особо работает
А в return true он вообще не работает. Вон я же уже постил ГК о жабьем bool mkdir(), в котором вообще не отличить "каталог уже есть" и "нет прав". Если надо отличить две ошибки - придется изобретать коды возврата. Но зачем, если в язык уже встроен более-менее адекватный механизм возврата ошибок?
wvxvw 02.04.2014 22:55 # 0
В том, который мы сейчас обсуждаем... который запостил автор этого говнокода.
И вообще, код в примере не решает эти задачи, он просто вместо if-else использует try-catch, но не пользуется ни одной из возможностей, которые try-catch предоставляет. Что там и как конкретно сгенерирует компилятор, да еще и в другом языке... по-моему тут на столько не важно, т.как мы уже получили оверхед на создание объекта инкапсулирующего операцию + замыкание в этом объекте. Накладные расходы на это все сто раз перекроют (скорее всего остуствующую) оптимизацию глобального отлова ошибок вместо ифа.
bormand 02.04.2014 23:18 # 0
Код в примере решает задачу о том, как из существующего (подчеркну это слово) action'а сделать функцию, пригодную для использования посреди асинхронной лапши аля continuation passing style.
Скорее всего рядом с описанной в топике функцией есть еще и другая, которая умеет передавать возвращаемое значение: А вот нужен ли в этом проекте CPS - это уже совсем другой вопрос для совсем другого треда. Да и без доступа к самому проекту на этот вопрос, наверное, и не ответить...
bormand 02.04.2014 23:25 # 0
А кто сказал, что сам a() ими не пользуется? Может быть a() как раз и использует неявный форвардинг ошибок из одной из вызываемых им функций? Или в нем 100500 вызовов функций, которые возвращают результат (или бросают исключение, которое сам a() обработать не может)? Мы же код этого a() не видим. Да и не увидим, т.к. там может быть абсолютно что угодно, лишь бы оно имело подходящую сигнатуру.
Ну не стоит же ради одного из использований этого a() в коде, приведенном в топике, переписывать a так, чтобы он отлавливал исключение и возвращал его (превращая функцию в возвращающую null или исключение)?
Может быть автор вообще какую-то стандартную функцию из библиотеки c# хочет туда передать в качестве экшена...
wvxvw 02.04.2014 23:31 # 0
Вобщем, если как попытка поставить заплатку на уже существующий дурацкий код, то хз. Как инструмент для постройки идеального общества - не подходит.
bormand 02.04.2014 23:40 # 0
Ну имхо это именно костыль для вписывания обычных функций в CPS лапшу... К которой у меня крайне негативное отношение (кроме случаев, когда этот CPS является результатом какого-то автоматического преобразования, который не надо писать/читать человеку).
> Как инструмент для постройки идеального общества - не подходит.
А это никто и не предлагал ;)
bormand 02.04.2014 22:18 # 0
Вот например file.exists():
true - да, такой файл есть
false - нет, такого файла нету
исключения - нет прав на чтение, сбой ФС и т.п. есть ли файл - мы не знаем
Stertor 02.04.2014 22:20 # +1
bormand 02.04.2014 22:21 # 0
Хе ;)
Ну например юзеру показать что-нибудь перед началом операции.
А непосредственно перед открытием файла их лепить глупо, согласен.
Stertor 02.04.2014 22:22 # 0
bormand 02.04.2014 22:26 # 0
Может. Но ситуации разные бывают.
Вот например какая-то операция занимает часа три. И где-то в конце этой операции надо прочитать некий файл. Показать ошибку через 3 часа будет вполне корректно, но не особо приятно для юзера.
Поэтому можно перед стартом операции убедиться в том, что все файлы на месте, и если чего-то не хватает - сказать юзеру об этом сразу. Если он что-то удалит потом - ну ССЗБ, получит ошибку через 3 часа ;)
bormand 02.04.2014 20:49 # 0
Т.е. правильный способ возврата ошибки в таком языке - это именно throw. Если я напишу Exception в возвращаемом типе и верну ошибку через return - я получу полное говно - функцию, которая возвращает... тип ошибки объединенный с типом ошибки.
bormand 02.04.2014 19:52 # 0
А если ошибку всегда выбрасывать, даже в функциях, возвращающих void которые юзаются только ради их побочного эффекта - получаем какое-никакое единообразие.
bormand 02.04.2014 19:41 # 0
Блин, в шарпике же есть замечательный механизм под названием async/await, которым все время любят хвастаться шарпеи... Так какого хрена выдумывать асинхронную лапшу с коллбеками аля нода жс, если есть возможно поюзать кошерный псевдосинхронный стиль?
neeedle 02.04.2014 19:56 # 0
И спорить особо об этой функции смысла нет.
Тут я думаю попытка супер-пупер повторного использования кода.
bormand 02.04.2014 20:03 # 0
Если бы не попытка M$ побыстрее закопать XP за счет неработоспособности на ней нового софта - все бы уже юзали фреймворк 4.5. Какой смысл оставаться на старых?
neeedle 02.04.2014 20:33 # 0
bormand 02.04.2014 20:40 # 0
kegdan 19.04.2014 14:47 # +1
Некрофил не смог молчать
guest 19.04.2014 17:27 # 0
kegdan 19.04.2014 17:33 # −1
guest 19.04.2014 17:52 # +1
kegdan 19.04.2014 18:00 # +1
А вас ебал.... Мммм.... Стивен Хокинг!
bormand 19.04.2014 18:03 # 0
Чтобы писать кроссплатформенные проги с GTK#. Ну и чтобы не платить за вижуалку.
Ваш кэп.
kegdan 19.04.2014 18:08 # +1
Хотите везде исполняемый код - пишите WCF и тонкий клиент под платформу.
defecate-plusplus 19.04.2014 18:30 # +1
Лучшие животные России
узнай больше >>
guest 19.04.2014 18:53 # 0
А на сисярпе вне вижуалки хотя бы теоретически можно платить?
kegdan 19.04.2014 18:57 # +2
guest 19.04.2014 19:00 # 0
Точно
> теоретически можно писать
Поправил
guest 19.04.2014 18:54 # 0
kegdan 19.04.2014 19:00 # +1
Балмер! Балмер! Балмер!
Причем тут змий?
guest 19.04.2014 18:19 # +3
kegdan 19.04.2014 21:44 # +2