Я знаю, что на этот вопрос был дан ответ, и я уже поставил его сам, но подумал, что добавлю следующее, поскольку я снова играл с ним, используя монады, и это казалось хорошим вопросом для публикации.
Прочитав эту статью о многопоточности монад, я смог прийти к добавьте следующее, расширив макрос m->
, определенный в статье, чтобы создать многопоточную монаду, возможно, для более простого использования. TBH, нет ничего проще, чем просто использовать some->
, но это было из личного любопытства.
Хорошо, для начала нужно определить какой-то нестандартный код, вот (на случай, если статья когда-нибудь исчезнет) определение многопоточной монады Джайлза:
(defn bind-monadic-expr-into-form [insert form]
(list 'm-bind insert
(if (seq? form)
`(fn [bound#] (~(first form) bound# ~@(rest form)))
`(fn [bound#] (~form bound#)))))
(defmacro m->
([m x]
`(with-monad ~m ~x))
([m x form]
`(with-monad ~m
~(bind-monadic-expr-into-form x form)))
([m x form & more]
`(m-> ~m (m-> ~m ~x ~form) ~@more)))
Теперь с этим вы можете определить макрос с нитями, возможно, как
(defmacro maybe->
([x] `(m-> ~maybe-m ~x))
([x form] `(m-> ~maybe-m ~x ~form))
([x form & more] `(maybe-> (maybe-> ~x ~form) ~@more)))
И используйте его как:
(maybe-> 1 inc)
=> 2
(maybe-> [1 2] (#(map inc %)))
=> (2 3)
(defn f1 [x] (+ 1 x))
(maybe-> 1 f1 f1)
=> 3
(maybe-> 1 f1 ((constantly nil)) f1)
=> nil
(maybe-> {:a 1 :b 2} :c inc)
=> nil
В этом контексте нет абсолютно никакого преимущества в использовании этого по сравнению с some->
, но монада m->
действительно добавляет некоторые интересные возможности в возможности создания макроса fail->
, как в статье, на которую я дал ссылку, которая предлагает больше, чем просто "ноль" в качестве возврата, давая Вы способность дифференцировать причину отказа.
person
Mark Fisher
schedule
18.05.2015