Fork me on GitHub
#clojure-russia
<
2017-08-29
>
kuzmin_m08:08:03

Привет! Кто как делает подобные вещи? letr из https://github.com/aphyr/dom-top

clojure
(defn register [ctx params]
  (letr [_ (if-let [err (check-logged-out ctx params)]
             (return [nil err]))
         _ (if-let [err (check-params params)]
             (return [nil err]))
         _ (if-let [err (check-registered ctx params)]
             (return [nil err]))

         user-id (create-user ctx params)
         _       (sign-in ctx user-id)]
    [{:user-id user-id} nil]))
Я не хочу тянуть сюда монаду Either и не хочу бросать исключения. Хотя это и так очень похоже на Either. Хотя могу и поменять свое мнение, если будет понятны их достоинства в этой ситуации. Ситуация может распространиться не только на обработку ошибок, но и на ранний возврат заначения.

delaguardo08:08:33

я бы так сделал

(let [err (or (check-logged-out ctx params)
              (check-params params)
              (check-registered ctx params))
      res (when-not err
            (create-user ctx params)
            {:user-id (sign-in ctx params)})]
  [res err])

kuzmin_m08:08:35

хм, занятно)

delaguardo08:08:01

можно и let на самом деле опустить, но читаться будет еще хуже

kuzmin_m08:08:26

по идее вот тут должен быть let

(when-not err
            (create-user ctx params)
            {:user-id (sign-in ctx params)})

kuzmin_m08:08:53

просто еще один уровень добавится

kuzmin_m08:08:05

а есть примеры раннего возратв?

delaguardo08:08:19

а зачем тут нужен let?

kuzmin_m08:08:44

именно в этом случае не нужен

kuzmin_m08:08:11

но появится еще какой-то вызов, и будет нужен

delaguardo08:08:04

а, ну как появится то конечно нужно будет что-то поменять) но тут вариантов как это сделать понятнее будет много, например вместо let внести все эти вызовы в body

kuzmin_m08:08:54

в боди их не вынесешь

kuzmin_m08:08:12

нужно же как-то результат возвращать

kuzmin_m08:08:38

твой пример идеален для конкретного случая

kuzmin_m08:08:53

может есть какая-то статейка про это?

kuzmin_m08:08:58

с разбором случаев

kuzmin_m08:08:07

где и что применять

delaguardo08:08:37

есть одна статья, кину если вспомню

kuzmin_m08:08:51

есть какие-то ключевики?

delaguardo08:08:36

там что-то было то ли про F#, толи про C# с неплохими илюстрациями в виде рельс

kuzmin_m08:08:56

это про either

kuzmin_m08:08:09

по F# вроде

kuzmin_m08:08:22

или они как раз объясняют без монад?

delaguardo09:08:05

с монадами конечно) но сама статья была неплохой

delaguardo09:08:19

да, она

kuzmin_m09:08:52

ты вообще видел в clojure где-нибудь монады в продакшене? это просто вопрос=)

kuzmin_m09:08:02

их реально кто-то использует?

delaguardo09:08:50

нет) по крайней мере мне не попадалось такого) но монады это способ реализации, типа один из многих. сам принцип лучше ухватить) мол реализуйте ваши функции как можно более изолированными + задайте стандартный интерфейс для проброса ошибки

kuzmin_m09:08:03

спасибо за пример)

kuzmin_m09:08:31

(defn call [ctx params]
  (let [err (or (check-logged-out ctx params)
                (check-params params)
                (check-registered ctx params))
        res (when-not err
              (let [user-id (create-user ctx params)
                    _       (sign-in ctx user-id)]
                {:user-id user-id}))]
    [res err]))
тут без let не обойтись, в твоем пример ошибка

delaguardo09:08:19

а… понял, если не менять sign-in, то да

kuzmin_m09:08:13

вот реализация рельс на кложе по той же статье

delaguardo09:08:39

спс, почитаю