Skip to content

Instantly share code, notes, and snippets.

@pasberth
Last active December 16, 2015 21:58
Show Gist options
  • Save pasberth/5503217 to your computer and use it in GitHub Desktop.
Save pasberth/5503217 to your computer and use it in GitHub Desktop.
マクロコンビネータ in infixing.clj
(use 'infixing.core)
(defn >>= [l f] (apply concat (map f l)))
(def mzero (list))
(defn return [x] (list x))
(def macro-combinator-rule
(rules
(infix-map 11 := (fn [x a] (fn [b] `(let [~x ~a] ~b))))
(infix-map 0 :in (fn [m a] (m a)))
(infix-map 0 :where (fn [a m] (m a)))
(infixr-space 2 (fn [m k] (fn [a] (m (k a)))))
(infix-map 9 '<- (fn [x a] (fn [b] `(>>= ~a (fn [~x] ~b)))))
(infix-map 5 :when (fn [m a] (fn [b] (m `(if ~a ~b mzero)))))
(infix-map 0 '| (fn [a m] (m `(return ~a))))))
(defmacro macro-combinator [code]
(infixing macro-combinator-rule code))
(println (macroexpand '(macro-combinator (x := 1, y := 2 :in (list x y)))))
(println (macroexpand '(macro-combinator (x | x <- '(1 2 3)))))
(println (macroexpand '(macro-combinator ((list x y) | x <- '(1 2 3) y <- (range (inc x) 5)))))
(println (macroexpand '(macro-combinator ((list x y) | x <- (range 1 5) :when (even? x)
y <- (range (inc x) 5) :when (odd? y)))))
(println (macro-combinator (x := 1, y := 2 :in (list x y))))
(println (macro-combinator (x | x <- '(1 2 3))))
(println (macro-combinator ((list x y) | x <- '(1 2 3) y <- (range (inc x) 5))))
(println (macro-combinator ((list x y) | x <- (range 1 5) :when (even? x)
y <- (range (inc x) 5) :when (odd? y))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment