Skip to content

Instantly share code, notes, and snippets.

@darkleaf
Last active November 27, 2019 10:32
Show Gist options
  • Select an option

  • Save darkleaf/db6df65f03bad07dd8608496c6d7b44c to your computer and use it in GitHub Desktop.

Select an option

Save darkleaf/db6df65f03bad07dd8608496c6d7b44c to your computer and use it in GitHub Desktop.

Подробно опишу суть вопроса.

Базовый пример:

(t/deftest simple-use-case
  (let [ef                (fn []
                            (eff
                              (let [rnd (! [:random])]
                                (- (* 2. rnd)
                                   1.))))
        effect-!>coeffect (fn [effect]
                            (match effect
                                   [:random] 0.5))
        result            (loop [[effect continuation] (e/loop-factory ef)]
                            (if (nil? continuation)
                              effect
                              (recur (continuation (effect-!>coeffect effect)))))]
    (t/is (= 0.0 result))))

Функция ef возвращает случайные числа (-1,1) и запрашивает результат эффекта [:random] - (0,1)

Для выполнения этой функции нужен внешний обработчик эффектов. Обработчик в цикле получает эффект и передает обратно коэффект. e/loop-factory позволяет сделать цикл или синхронным на loop/recur или рекурсивно-асинхронным:

(fn main-loop [[effect continuation] callback]
  (if (nil? continuation)
    (callback effect)
    (js/setTimeout #(main-loop (continuation (effect-!>coeffect effect))
                               callback)
                   0)))
(main-loop (e/loop-factory ef) (fn callback [result] ...))

Вопрос Функция effect-!>coeffect может принимать контекст (state), например так:

(loop [state                 0
       [effect continuation] (e/loop-factory ef)]
  (if (nil? continuation)
    effect
    (let [[state coeffect] (effect-!>coeffect state effect)]
      (recur state (continuation coeffect)))))

или останавливать цикл раньше:

(loop [[effect continuation] (e/loop-factory ef x)]
  (if (nil? continuation)
    effect
    (let [coeffect (effect-!>coeffect effect)]
      (if (reduced? coeffect)
        (unreduced coeffect)
        (recur (continuation coeffect))))))

Есть способ разделить цикл и дополнительные поведения? Так, чтобы это было похоже на композицию middlewares.

@darkleaf
Copy link
Author

@darkleaf
Copy link
Author

вопрос снят. решение найдено.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment