Skip to content

Instantly share code, notes, and snippets.

@jarohen
Last active August 29, 2015 14:22
Show Gist options
  • Save jarohen/29bc3c7b3272eb65d07a to your computer and use it in GitHub Desktop.
Save jarohen/29bc3c7b3272eb65d07a to your computer and use it in GitHub Desktop.
Ideas for making 'yo-yo' easier to work with (https://github.com/james-henderson/yoyo)
(comment
;; Option 1 - the 'fn staircase' (current)
(defn make-system [latch]
(with-db-pool {...}
(fn [db-pool]
(let [web-config (read-config ...)]
(with-cljs-compiler {:config web-config
...}
(fn [cljs-compiler]
(with-web-server {:handler (make-handler {:cljs-compiler cljs-compiler
:db-pool db-pool
:config web-config})
:port ...}
(fn [server]
(latch)))))))))
;; ---
;; Option 2 - a 'let' macro (essentially Haskell's 'do' syntax sugar
;; over a continuation-like monad - with the macro assuming the last
;; argument to each expression on the RHS being the continuation)
(:require [yoyo :refer [ylet]])
(defn make-system [latch]
(ylet [db-pool (with-db-pool {...})
:let [web-config (read-config ...)]
cljs-compiler (with-cljs-compiler {:config web-config
...})
server (with-web-server {:handler (make-handler {:cljs-compiler cljs-compiler
:db-pool db-pool
:config web-config})
:port ...})]
(latch)))
;; ---
;; Option 3 - going slightly further - removing the latch and naming the system
(:require [yoyo :refer [defsystem]])
(defsystem my-system
[db-pool (with-db-pool {...})
:let [web-config (read-config ...)]
cljs-compiler (with-cljs-compiler {:config web-config
...})
server (with-web-server {:handler (make-handler {:cljs-compiler cljs-compiler
:db-pool db-pool
:config web-config})
:port ...})])
;; ---
;; We can, of course, offer all three!
;; ---
;; Implementations:
(defmacro ylet [bindings & body]
(assert (even? (count bindings)) "'ylet' must have an even number of bindings")
(if-let [[bind expr & more] (seq bindings)]
(if (= bind :let)
`(let ~expr
(ylet ~more ~@body))
`(~@expr (fn [~bind]
(ylet ~more ~@body))))
`(do
~@body)))
(defmacro defsystem [name bindings]
`(defn ~name [latch#]
(ylet ~bindings
(latch#))))
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment