Skip to content

Instantly share code, notes, and snippets.

@qerub
Last active August 29, 2015 14:07
Show Gist options
  • Save qerub/216a7945831a30ed0d63 to your computer and use it in GitHub Desktop.
Save qerub/216a7945831a30ed0d63 to your computer and use it in GitHub Desktop.
[Clojure] fancy-defn: Proof of concept of schema.core/defn augmented with automatically generated clojure.core.typed annotations via circle.schema-typer
(ns fancy-defn
(:require [schema.core :as s]
[clojure.core.typed :as t]
[circle.schema-typer :as st]))
;; Schemas created with s/defn end up using this.
(defmethod st/convert schema.core.One [schema]
(assert (= false (:optional? schema))) ;; No support for optional arguments yet.
(st/convert (:schema schema)))
(defmethod st/convert schema.core.FnSchema [schema]
;; Not sure why the input schema vector is wrapped in a seq...
(assert (= 1 (count (:input-schemas schema))))
;; Some good old prn debugging output!
;; (prn "Output:" (:output-schema schema) "=>" (st/convert (:output-schema schema)))
;; (prn "Input:" (:input-schemas schema) "=>" (map st/convert (first (:input-schemas schema))))
(let [input-types (mapv st/convert (first (:input-schemas schema)))
output-type (st/convert (:output-schema schema))]
(conj input-types :-> output-type)))
(defmacro schema-ann [name]
(let [var (resolve name) ;; Will this resolve `name` in the right namespace?
schema (:schema (meta var))]
`(t/cf (t/ann ~name ~(st/convert schema)))))
(defmacro fancy-defn [name & rest]
`(do (s/defn ~name ~@rest)
(schema-ann ~name)))
(comment
;;; Example usage
(fancy-defn yell! :- String [s :- String] (str s "!!!"))
(s/fn-schema yell!)
;; (=> java.lang.String java.lang.String)
(t/cf yell!)
;; [java.lang.String -> java.lang.String]
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment