Fork me on GitHub
#specter
<
2023-05-10
>
pppaul17:05:30

it's been hard for me to come up with problems that i want to solve with specter, but i have one now. i have parts of my data-structure where i have meta data on a list/vector, i want to merge/transform each item in the list with that meta data. i typically do this sort of thing with walks and core.match, but i would like to see how this looks like in specter.

;; input
{
 :example-meta
 ^{:custom/template "example/file/path.file"}
 [
  {:summary              "all fields filled in"}
  {:summary              "missing single-file uploads"}  
  ]
 }

;; output =>
{
 :example-meta 
 [
  {:summary         "all fields filled in"
   :custom/template "example/file/path.file"}
  {:summary "missing single-file uploads"} 
  :custom/template "example/file/path.file" 
  ]
 }
so, i think i know how to do this with a nested transformation, but i'm wondering if this can be done with a single transformation. can a single transformation detect the key i care about in meta, then operate on the structure the meta-data is attached to?

pppaul18:05:49

(transform [MAP-VALS
              (view (juxt (comp #(select-keys % [:custom/template]) meta) identity))
              (pred first)]
             (fn [[meta resources]]
               (->> resources
                    (transform ALL (partial merge-with str meta)))
))
i came up with this, i tried experimenting with a lot of specter functions, including multi-path i found view to be very useful, and multi-path does almost what i want (which is something like juxt). i expect there is a much better way to do this. (comp select-keys... seems like it's redundant with other specter functions

pppaul18:05:51

(merge-with str ... is intentional, meta data in this case would be assumed to be a prefix

rolt08:05:19

you can use collect

rolt08:05:36

(transform [:example-meta
               (collect-one META #(select-keys % [:custom/template]))
               ALL]
              (fn [meta resources] (merge-with str meta resources))
              data)

rolt08:05:10

or even:

(transform [:example-meta
               (collect-one META (submap [:custom/template]))
               ALL]
              (fn [meta resources] (merge-with str meta resources))
              data)

pppaul17:05:40

thanks, I'll try these out