Fork me on GitHub
#specter
<
2019-01-31
>
steveb8n03:01:42

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

steveb8n03:01:02

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?

steveb8n05:01:07

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.

nathanmarz07:01:40

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

🙏 5
steveb8n07:01:10

thanks. let me try that

steveb8n07:01:56

awesome. works like a charm.