Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
(ns variant
(:require [clojure.core.typed :as t]))
(t/defalias V
(t/Rec [V]
(t/U '[':lambda t/Sym V]
'[':if V V V]
'[':val t/Any])))
(t/ann command [V -> t/Str])
(defmulti command first)
(defmethod command :lambda
[[_ s body]]
(command body))
(defmethod command :val
[[_ val]]
(str val))
(defmethod command :if
[[_ test then else]]
(str (map command [test then else])))

jneen commented Nov 22, 2014

And for convenience,

(defmacro defvariant [name variant-binder body]
  (let [[tag & binders] variant-binder]
    `(defmethod ~name ~tag [[_ ~@binders]] ~body)

(defvariant command [:print val]
  (println val))

jneen commented Nov 22, 2014

and if you like, it's small but not insignificant

(defmacro defmulti-variant [name & args]
  `(defmulti ~name first ~@args))

Maybe it could use a better name though...

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