views:

370

answers:

1

I'd like to be able to do something like this:

(search data 
  list?
  (fn [x] (and (list? x) (= 4 (first x))))
  (fn [x] (and (set? x) (contains x 3))))

And have it recursively search a nested data structure data:

  1. first for the shallowest lists (might be in a set of sets, for example).
  2. then within those lists for the shallowest lists who's first element is 4.
  3. then in those lists for the shallowest sets that contain 3.
  4. finally returning a list of items found in step 3.

Before I reinvent the wheel, is there a standard way of doing this?

+4  A: 

Clojure has standard ways for traversing trees. You should look into clojure.zip and look into tree-seq as well.

(loop [loc dz] 
  (if (end? loc) 
    (root loc) 
    (recur (next (if (= '* (node loc)) 
                   (replace loc '/) loc))))) 

(loop [loc dz] 
  (if (end? loc) 
    (root loc) 
    (recur (next (if (= '* (node loc)) 
                   (remove loc) loc)))))

These two examples at the end of clojure.zip seem to make it clear that you don't need to know what the data structure looks like. The use of loop also shows that you could easily accumulate only the values you are interested in as you traverse the data structure.

dnolen
zip seems like it's useful if you already know your data structure, and where within a larger structure you should be looking. tree-seq is a bit counterproductive as it masks the datastructure in question and makes it appear as a sequence so you won't even know if you're in a list of a list, or a set of a set.I gave you a +1, as these might be useful in building the function I'm looking for.
z5h
For example, I could set the children function of tree-seq to inject tags that let me know when I'm traversing into or out-of a sub-structure. Then the consuming search function can keep track of depth and where within the larger structure it is.
z5h