(defmacro clj-loop ``A drop-in replacement for Clojure's loop form. Useful for the current project of converting Clojure code to Janet. `` [bindings & body] (assert (even? (length bindings)) "Binding tuple must have an even number of terms") (def names @[]) (def args @[]) (loop [i :range [0 (length bindings)]] (if (even? i) (array/push names (get bindings i)) (array/push args (get bindings i)))) ~(do (defn recur [,;names] ,;body) (recur ,;args))) (defmacro defn+ [name & clauses] ~(defn ,name [& args] (print "before do") (do (def arities @{}) (def clauses ,clauses) (def bindingses (map first clauses)) (def bodies (map |(slice $ 1) clauses)) (print "before loop") (loop [i :range [0 (length clauses)]] (def bindings (get bindingses i)) (def arity (length bindings)) (assert (not (get arities i)) "Clauses must have different arities") (def body (get bodies i)) (def clause ~(fn ,name ,bindings ,;body)) (put $arities arity clause)) (print "before quasiquote") (fn [& args] (def arity (length args)) (def clause (get arities arity)) (assert clause "No clause with that arity") (clause ;args))))) (defn+ add ([] 0) ([x] x) ([x y] (+ x y))) (macex1 '(defn+ add ([] 0) ([x] x) ([x y] (+ x y))))