I was pondering a little on how meander could handle above situation a little more gracefully. I think similar things have been discussed in here before, but I figured I might as well throw my hat in the ring:
(m/match {:package 1
:items
[{:price 34.50M
:subitems
[{:parts [{:id 2} {:id 3}]}
{:parts [{:id 4} {:id 5}]}]}
{:price 23.21M
:subitems
[{:parts [{:id 6} {:id 7}]}
{:parts [{:id 8} {:id 9}]}]}]}
{:package ?package
:items
[(m/scope !items
{:price !items.?price
:subitems
[{:parts [{:id (m/and !items.!parts !parts)} ...]} ...]})
...]}
{:package ?package
:items !items})
;; =>
{:package 1
:parts [2 3 4 5 6 7 8 9]
:items [{'?price 34.50M
'!parts [2 3 4 5]}
{'?price 23.21M
'!parts [6 7 8 9]}]}
The mental model is pleasantly straightforward: m/scope is more or less equivalent to pulling the collection out and running (m/search coll (m/scan )) on it, and the scoped var's value is a map of the vars bound inside that m/search. It maintains intuition about how logic variables and memory variables work: within a scope, a logic var will only have one value, whereas a memory var is always a collection of values. m/scope's mode of operation is also conceptually straightforward: for each match on the target pattern, all scoped variables are "fresh".
I'm not sure how useful it would be to use logic var (rather then memory var) scopes, but there's nothing logically there's nothing wrong with it, it'd just give you a single map rather than a collection of them. Thoughts?