Skip to content

Instantly share code, notes, and snippets.

@frenchy64
Created November 22, 2014 21:08
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save frenchy64/c7e1a318c67baf7576c5 to your computer and use it in GitHub Desktop.
Save frenchy64/c7e1a318c67baf7576c5 to your computer and use it in GitHub Desktop.
(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
Copy link

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
Copy link

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