Create a record of the same type as another

Viewed 230

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).

2 Answers
Related