This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2019-01-08
Channels
- # announcements (6)
- # aws (1)
- # beginners (64)
- # boot (22)
- # calva (9)
- # cider (109)
- # clara (4)
- # cljs-dev (29)
- # clojure (112)
- # clojure-europe (2)
- # clojure-italy (6)
- # clojure-nl (3)
- # clojure-russia (215)
- # clojure-spec (80)
- # clojure-uk (13)
- # clojurescript (150)
- # code-reviews (3)
- # core-async (7)
- # cursive (37)
- # data-science (11)
- # datomic (76)
- # figwheel-main (6)
- # fulcro (56)
- # jobs (3)
- # jobs-discuss (22)
- # juxt (4)
- # off-topic (11)
- # pathom (16)
- # planck (5)
- # portkey (63)
- # re-frame (22)
- # reagent (3)
- # remote-jobs (1)
- # ring-swagger (5)
- # shadow-cljs (3)
- # testing (2)
- # tools-deps (6)
Привет. Есть исключительные ситуации, а есть ожидаемые. Под исключинтельными ситуациями я понимаю: закончилась память, закончился диск, разорвалось соединение и т.п. И это реализуют с помощью исключений. А есть вполне ожидаемые прерывания основного потока выполнения. Пользователь ввел невалидные данные. Пользователь не имеет прав на операцию. Обычно советуют исползовать either, maybe и т.п. для этого случая. На первый взгляд отличие исключения от either в том, что исключение дороже из-за стек трейса. В для either мы должны особым образом структурировать код. А результат один - всплывание ошибок. Только в одном случае это делает jvm, а в другом мы сами. Так может не мучаться и использовать исключения без стектрейсов? Что думаете? Есть какие-то практические примеры?
https://dev.clojure.org/jira/browse/CLJ-2423 Miller против 🤷
> Обычно советуют исползовать either, maybe и т.п. для этого случая. мне кажется формулировка “обычно советуют” - ложна. Кто, где, почему? > На первый взгляд отличие исключения от either в том, что исключение дороже из-за стек трейса. дороговизна понятие относильное, но основное отличие - контекст исключение может быть поймано где выше в асбтракции и что с ним делать? тот же go to - не просто же так считается плохим паттерном
и почему в итого either vs exception?
других вариантов нет?
вернуть ошибку
какую проблему вы хотите решить
Есть некий сценарий. что-то получить на вход проверить сделать операцию проверить контекст сделать операцию проверить результат что-то сделать
т.е. подходит и exception и either но вроде как exception для этого не стоит использовать а either - нужно код особым образом писать
Failjure
все библиотеки заставляют особым образом код структурировать, чтобы можно было ошибку на верх передать я не очень понимаю зачем, если есть исключения
Нет right
Тогда if - это монады )
С такой логикой
А что важно?
Контекст
Исключения могут быть обработаны где выше
Без доступа к контексту
В общем обсуждение довольно деструктивное
Какие проблемы решаются - я не понимаю
Так что врядли могу что подсказать
Если исключения работают - используйте
Да кто знает
Потом ломай голову
Everyone here is repeating the phrase “exceptions are for exceptional circumstances”, but that really doesn’t give any understanding of why its bad to use them for unexceptional circumstances. I need more than that. Is the performance hit of throwing exceptions really that bad? Are there any benchmarks available?
На предыдущем проекте у нас было вида 3 разных имплементаций монад. Всё такой ад, даже с тредин-макросами, которые сами заворачивают/разворачивают конвертики эти. Самый ништяк - эксепшены с ex-data, и потом диспатчить в трай по типу эксепшена (какой-нибудь :error/type в ex-info)
@U051HUZLD а есть ссылка на вброс?
Rich Hickey Maybe
опять побуду капитаном 😉
но в том толке maybe расматривается в другом контексте
Там реально надо каждую функцию или лифтить или рефакторить, в итоге запутываешься в бюрократии на ровном месте, где надо и где не надо
то, что если метод возвращает мейби, а потом всегда только занчение и нужно всех потребителей переписывать?
С тз поддержки кодобазы - это был major gemor. И оно ж потом как рак метастазы во все уголки проекта пускает
(defprotocol Foo
(foo [x]))
(extend-protocol Foo
Object
(foo [_] :obj))
(foo 1)
(foo false)
@U051HUZLD а к чему в итоге то пришли? исключения?
Не всё завернуто как минимум потому что тебе может из жавы примитив предыдущая ф-я вернуть после интеропа
К тому, что времени выкашивать нет. Там до сих пор срач, где эксепшены, где одни монады, где катс, где мапы еррор/валью, где вектора лево/право
в идеологии flow есть нормальные значения, а есть exception instances которые сингализируют об ошибке
насчет дороговизны трейсов, есть возможность использовать кастомный контейнер вместо ExceptionInfo, я сейчас думаю над этим. Хотел добавить поддержку "no stacktrace" в ex-info в core, но зареджектили, что вобщем-то ожидаемо
Если я правильно понял, то в flow используются идеи continuation-passing style (CPS). А исключения можно реализовать через континуации. И это равномощные вещи. Только исключения в jvm из коробки есть. Я пока не пробовал использовать исключения для ожидаемых ответвлений оснвного потока вычислений. Но пока единственная “проблема” - медленные исключения. Ну один случай из 10 будет чуть медленнее, если пользователь ошибется и введет что-то не то. И видимо из-за этого Миллер в в тикете отписался, что не видит проблем. Плюс, если кто-то добавил новый тип исключения, и забыли добавить его обработку, то тут стек-трейс полезен. Я где-то с полгода назад бенчмарки делал, и уже не помню, но исключения вроде раз в 100 или в 1000 были медленнее. Но это миллесекунды и наносекунды. Но зато нет накладных расходов в основном потоке исполнения. Я сравнивал исключения, better-cond, вложенные if и свою первую реализацию either. @U4BEW7F61
flow просто определяет инстанс исключения как fail, и дает 2 хелпера базирующихся на этом утверждении
(defn check-login [req next]
(if (:user req)
next
{:error "Login required" :code 401}))
Для понимания, я сам either делал https://github.com/darkleaf/either Но тогда не до конца разобрался зачем все это нужно. И сейчас кажется - что обычные исключения это подходящее решение. И как-то не убедительно для меня использование either-like подходов. Может быть я о каких-то случаях не знаю. Попробую свой either выпилить, может быть и найду такой случай.
(defn remove-calendar-parent!
[{:keys [user db conn admin?] :as ctx} {:keys [spaceId]} _]
(->> (ensure-login user)
(then (fn [_] (find-space db spaceId)))
(then #(check-edit-ability % user admin?))
(then #(perform-remove-calendar-parent conn %))
(else respond-with-error)))
да даже тот же вложенный try/catch можно в специализированную фукнцию завернуть, что бы вычисление в номальную ветку возвращалось
т.е. мы перешли в область нравится/не нравится и измеримых факторов, кроме скорости не осталось это не наезд, просто констатация у всех есть вкусы и это нормально
ну, я пробовал делать ещё такое:
для flow использовать обычный some->
по операциям, возвращающим nil
сами операции можно оборачивать макросами, которые для nil
(или при исключениях) аккумулируют результат во что-то соответстующее контексту
получалось прикольно
можно смешивать результат от операций, которые по разному работают (возвращают nil
, бросают исключение) и самому определять форму аккумулятора «ошибки» в конкретном контексте
Если кому-то интересны continuations - то можем обсудить. Я собрал jvm от проекта loom, который добавляет поддержку файберов. Вот маленький пример
(ns yield
(:import
[java.lang ContinuationScope Continuation]))
(let [scope (ContinuationScope. "example")
f (fn []
(prn :fn-start)
(Continuation/yield scope)
(prn :fn-end))
cont (Continuation. scope (fn []
(prn 1)
(Continuation/yield scope)
(f)))]
(while (not (.isDone cont))
(.run cont)
(prn :control)))
;; 1
;; :control
;; :fn-start
;; :control
;; :fn-end
;; :control
ну, я пробовал делать ещё такое:
для flow использовать обычный some->
по операциям, возвращающим nil
сами операции можно оборачивать макросами, которые для nil
(или при исключениях) аккумулируют результат во что-то соответстующее контексту
получалось прикольно
можно смешивать результат от операций, которые по разному работают (возвращают nil
, бросают исключение) и самому определять форму аккумулятора «ошибки» в конкретном контексте