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
: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.