I have a case where I would like to create a new instance of a record based on the type of a record instance that is coming as an argument together with a map of attributes.
(defn record-from-instance
[other attrs]
;; Code that creates the new record based on "other"
)
What I have right now is something among the lines:
(defn record-from-instance
[other attrs]
(let [matched (s/split (subs (str (class other)) 6) #"\.")
path (s/join "." (pop matched))
class-name (peek matched)]
((resolve (symbol (str path "/" "map->" class-name))) attrs)))
Is there any other simpler more idiomatic way to do this that I cannot see?
Thanks!
EDIT
To give some more details I am constructing an AST with nodes being records and I am using a zipper to visit and possibly alter / remove parts of the AST. I have an IZipableTreeNode protocol
(defprotocol IZipableTreeNode
(branch? [node])
(children [node])
(make-node [node children]))
Between the different types that implement the IZipableTreeNode is IPersistentMap
IPersistentMap
(branch? [node] true)
(children [node] (seq node))
(make-node [node children]
(let [hmap (into {} (filter #(= (count %) 2)) children)]
(if (record? node)
(record/from-instance node hmap)
hmap)))
When a visitor say deletes a field from a node (or alters it) the make-node gets called with node being the record AST node and children the new key/value pairs (that may not contain some of the fields in node).