specter

2023-04-23T01:00:41.508599Z

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 {})

cheewah 2023-04-25T04:56:05.712659Z

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

2023-04-23T01:39:40.088249Z

(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

2023-04-23T01:58:50.637589Z

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.