Skip to content

Instantly share code, notes, and snippets.

@tangrammer
Last active August 29, 2015 14:08
Show Gist options
  • Save tangrammer/3a1b9cdc79d2b3a766ea to your computer and use it in GitHub Desktop.
Save tangrammer/3a1b9cdc79d2b3a766ea to your computer and use it in GitHub Desktop.
try defrecord wrapper
(ns wrapper.core
(:require [schema.core :as s]
[clojure.pprint :refer (pprint)]
[clojure.tools.namespace.repl :refer (refresh refresh-all)]))
(defprotocol Welcome
(greetings [_] )
(say_bye [_ a b]))
(defrecord Example []
Welcome
(greetings [this] "my example greeting!")
(say_bye [this a b] (str "say good bye" a b))
)
(greetings (Example.))
;;=> "my example greeting!"
(defn get-supers [instance]
(filter (fn [ty] (some #(.contains (str ty) %) #{"wrapper"}))
(->> (supers (class instance)))))
(get-supers (Example.))
;;=> (wrapper.core.Welcome)
(defn get-methods [instance]
(map (fn [sup]
[sup (->> (.getDeclaredMethods sup)
(map #(vector (count (.getParameterTypes %)) (.getName %)))
(into #{}))])
(get-supers instance)))
(get-methods (Example.))
;;=> ([wrapper.core.Welcome #{[2 "say_bye"] [0 "greetings"]}])
(defn get-params [n]
(vec (take (inc n)
(conj (map (comp symbol #(str % "#") char) (range 97 123)) (symbol "this#")))))
(get-params 3)
;;=> [this a b c]
(defn adapt-super-impls
"java-meta-data"
[[prot-class prot-fns]]
[prot-class (map (fn [[b c]] [(symbol c) (get-params b)])
prot-fns)])
(adapt-super-impls (first (get-methods (Example.))))
;;=> [wrapper.core.Welcome ([say_bye [this a b]] [greetings [this]])]
(defmacro protocol-impl [protocol-definition]
``(defrecord ~(symbol "my-wrapper") [~(symbol "e#")]
~@(let [[type# protocol-functions#] ~protocol-definition]
(conj
(map
(fn [[function-name# function-args#]]
`(~function-name# ~function-args#
(~function-name# ~(symbol "e#") ~@(next function-args#))))
protocol-functions#) type#))
))
(protocol-impl (adapt-super-impls (first (get-methods (Example.)))))
;;=> (clojure.core/defrecord
;; my-wrapper
;; [e#]
;; wrapper.core.Welcome
;; (say_bye [this# a# b#] (say_bye e# a# b#))
;; (greetings [this#] (greetings e#)))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment