Search code examples
clojuresymbolsdeftype

How to create a type in Clojure from an input of Strings for symbol names?


I'm trying to create a list of types - so that I can map over a list of Strings and create all the types I need.

This is where I'm aiming for:

(defprotocol P (methodname [arg1]))

(deftype T [f] P (methodname [arg1] (println "methodname called")))

For just a single instance of generating a type from String names - I'm trying:

(defmacro create-type [type-name field-list protocol-name protocol-sig]
  `(deftype ~type-name ~field-list ~protocol-name ~protocol-sig))

(create-type (symbol "type-name") [field1]  (symbol "P") (methodname [arg1]))

This fails with:

ClassCastException clojure.lang.PersistentList cannot be cast to clojure.lang.Symbol  clojure.core/ns-resolve (core.clj:4026)

My question is: How to create a type in Clojure from an input of Strings for symbol names?


Solution

  • Bit hacky, but works for me:

    (defprotocol P (methodname [arg1]))`
    
    (defmacro gen-type [type-name field-list proto-name proto-sig]
    `(load-string (str "(deftype " ~type-name " " ~(str field-list) ~(str proto-name) ~(str proto-sig) ")")))
    
    (gen-type "T" [f1 f2] P (methodname [arg1]))
    

    So I'm just basically building a string and evaluate that with the reader.

    Without load-string (still not too flexible, but does the job):

    (defmacro gentype [t f p m a b]
      `(deftype ~(symbol t) ~f ~p (~m ~a ~b)))
    
    (gentype "T3" [f1 f2] P methodname [arg1] (prn arg1))