MK
(u/<<-
(or (!already-logged-in session))
(or (!has-additional-messages msgs))
(let [user (->user msgs password->digest)])
(or (!has-validation-errors user))
(let [user (fill-id user new-user-ids)
id (-> user agg/root :agg/id)])
{:set-session (assoc session :current-user-id id)
:persist [user]
:reaction {:type :show-screen
:name :main}}))
Я разбирался с эффектами, коэффектами, чистыми фунциями, functional core imperative shell, т.е. о том, как сделать логику принятия решений чистой, а работу с побочными эффектами максимально тупой.
Нашел как сделать suspendable функции, они же async/await и yield, просто на читых функцях и небольшом макросе.
Без project loom и т.п.
В порядке усложнения
https://github.com/darkleaf/suspendable-process/blob/master/src/suspendable_process/a.clj
https://github.com/darkleaf/suspendable-process/blob/master/src/suspendable_process/b.clj
https://github.com/darkleaf/suspendable-process/blob/master/src/suspendable_process/c.clj
Есть функция process, которая описывает логику работы программы, т.е. functional core.
И есть интерпретатор эффектов, т.к. imperative shell.
Пример искусственный, но в нем есть ветвление и цикл/рекурсия.
Более-менее реальный пример
https://github.com/darkleaf/publicator/blob/3.1/core/src/publicator/use_cases/user/register2.clj#L45-L63
https://github.com/darkleaf/publicator/blob/3.1/core/test/publicator/use_cases/user/register2_test.clj
но тут эффекты в виде хэшмап, а не векторов.
@razum2um ты как раз спрашивал про интерпретатор.