specter 2023-04-23

i just started playing around with specter, and i'm trying to do something like filter a map's keys by some nested value existing.

;; this code finds the :to-name values, but i want it to act like a filter, keeping keys in the map which have this property
(let [templates               {
                               :user/company-member-removed {:default-params        {:from-subject "Membership Revoked"},
                                                             :required-params       #{:to-email :to-name},
                                                             :type                  :sendpulse,
                                                             :variables             #{:company_name},
                                                             :sendpulse/template-id 12345},
                               }
      templates-with-to-names (->> templates
                                   (select [MAP-VALS :required-params ALL (s/pred= :to-name)]))
      ]
  templates-with-to-names)
i would normally do something like this via (map (juxt key my-filter)) and remove the nil vals then (into {})

am new to specter as well and your use of transform to 'remove' unwanted entries is an interesting one, definitely something to add to my specter toolkit if there isn't a more idiomatic way. meanwhile i play around a little and found the following no transform version gets pretty close

(select [ALL (selected? [LAST :required-params ALL (pred= :to-name)])] template)
but the output is vector instead of map

(let [templates               {
                               :user/company-member-removed {:default-params        {:from-subject ""},
                                                             :required-params       #{:to-email :to-name},
                                                             :type                  :sendpulse,
                                                             :variables             #{:company_name},
                                                             :sendpulse/template-id 54321},
                               }
      templates-with-to-names (->> templates
                                   (select [MAP-VALS
                                            (selected? [:required-params ALL (pred= :to-name)])]))      
      ]
  templates-with-to-names)
;;=>
;; [
;;  {:default-params        {:from-subject "Email Verification"},
;;   :required-params       #{:to-email :to-name},
;;   :type                  :sendpulse,
;;   :variables             #{:registration_link},
;;   :sendpulse/template-id 123456}
;;  ...
;;  ]
got to this point, i would like to preserve the map keys, i'm not sure why they got dropped

templates-with-to-names (->> templates
                                   (transform [ALL (not-selected? [ALL :required-params ALL (pred= :to-name)])]
                                     NONE))
i managed to find something that works. any input into if this looks ok or not (am i doing something weird?) is welcome.