specter

Latest version: 1.1.3
steveb8n 2019-01-31T03:42:42.056300Z

I’m having trouble with a recursive requirement. Here’s the example:

(->> {:gender :male
        :type    :person
        :name    "Luke"
        :mother  {:gender :female
                  :type :person
                  :name "Padme"}
        :friends [{:gender :male
                   :type :person
                   :name "Han"}
                  {:gender :male
                   :type :person
                   :name "Chewbacca"}]
        :mentors {:type   :group
                  :people [{:gender :male
                            :type :person
                            :name "Obiwan"}
                           {:gender :male
                            :type :person
                            :name "Yoda"}]}}
       (select [(recursive-path [] p
                                (if-path (fn [v] (and (map? v) (:gender v)))
                                         (continue-then-stay (multi-path [(must :friends) ALL]
                                                                         [MAP-VALS #(:gender %)])
                                                             p)))]))
=>
[{:gender :male, :type :person, :name "Han"}
 {:gender :male, :type :person, :name "Chewbacca"}
 {:gender :female, :type :person, :name "Padme"}
 {:gender :male,
  :type :person,
  :name "Luke",
  :mother {:gender :female, :type :person, :name "Padme"},
  :friends [{:gender :male, :type :person, :name "Han"} {:gender :male, :type :person, :name "Chewbacca"}],
  :mentors {:type :group,
            :people [{:gender :male, :type :person, :name "Obiwan"} {:gender :male, :type :person, :name "Yoda"}]}}]
How can I get it to also return the mentors? They are :persons as well

steveb8n 2019-01-31T03:46:02.057700Z

multi-path only seems to support 2 variations. I guess another way of asking this is how can I combine the selections of 3 paths into 1?

steveb8n 2019-01-31T05:57:07.060Z

One way would be to use a clojure.walk to extract all :person maps and wrap that in a specter nav (maybe view). I can’t use specter/walker because it stops on matches in each branch so it would only return 1 mentor. ideally I’d like some specter native nav composition but can’t see how.

nathanmarz 2019-01-31T07:34:40.060600Z

@steveb8n I think you're looking for:

(def PEOPLE
  (recursive-path [] p
    (continue-then-stay
      (multi-path
        (must :mother)
        (must :father)
        [(must :friends) ALL]
        [(must :mentors) :people ALL]
        )
      p
      )))

🙏 1
steveb8n 2019-01-31T07:35:10.060700Z

thanks. let me try that

steveb8n 2019-01-31T07:36:56.060900Z

awesome. works like a charm.