Fork me on GitHub
#specter
<
2017-05-08
>
mac21:05:45

@nathanmarz I looked at traverse and not sure it does what I need. I have a tree structure of deeply nested records which I would like to walk/transform. Some of these are condition records that should stop navigation of the subtree underneath if the condition (a vector of predicate functions) does not return true. Does that make sense? I have tried to illustrate the structure below. Navigation should not get to the action records of type :three and :three-and-a-half but allow me to select/transform the other records based on some criteria.

nathanmarz22:05:43

@mac what do you run the predicate function on?

nathanmarz22:05:59

what is #(= % 3) supposed to receive as input?

mac22:05:12

@nathanmarz I will pass it the children it is guarding and probably an environment of some sort (a map most likely).

nathanmarz22:05:03

from your prior description it sounded like you needed to get some functions out of a nested structure and run them

nathanmarz22:05:29

to do this, once you get to a condition, just use a function to filter it

nathanmarz22:05:25

(defn cond-filter [cond]
  ;; return true if every condition function returns true)

nathanmarz22:05:53

then your path would contain [... cond-filter :actions ALL ...]

mac22:05:23

@nathanmarz Sorry for the confusion. I only need to run the functions to determine if the subtree they are guarding should be walked or skipped.

nathanmarz22:05:06

@mac does making a function that runs the condition functions solve your problem?

mac22:05:42

@nathanmarz I don't think so. Only if I the result could control if the children of the Condition record are walked or not - the problem is I don't know how to do that. Been looking at zippers too, but last time I dealt with them it was painful 🙂

nathanmarz23:05:42

it does control that

nathanmarz23:05:55

that's exactly what it does

nathanmarz23:05:43

your path should navigate to condition, then run a filter function there to do all the logic of testing the predicates against the guarded children

nathanmarz23:05:51

if that returns true, then it can continue walking the actions

nathanmarz23:05:57

if it returns false, then the actions will not be walked

mac23:05:12

And the remainder of the structure will still be walked?

mac23:05:26

@nathanmarz I might be missing something here, but I don't have a path at all, only a walker.

nathanmarz23:05:00

you mean you're using the walker navigator?

nathanmarz23:05:27

wrap it in a recursive-path

nathanmarz23:05:13

what are you walking to?

nathanmarz23:05:19

Action or Condition?

nathanmarz23:05:55

actually, is your goal to just retrieve all actions that are properly guarded?

mac23:05:18

Yes, and potentially transform them.

nathanmarz23:05:51

(def SATISFACTORY-ACTION-NODES
  (recursive-path [] p
    (if-path #(instance? Condition %)
      [cond-filter :children ALL p]
      (continue-then-stay
        :children
        ALL
        p
        ))))

nathanmarz23:05:55

you want something like that

nathanmarz23:05:14

I don't think you want to use walker

nathanmarz23:05:43

it's always better to encode the precise structure of your data rather than brute force it with walker

nathanmarz23:05:34

an alternative way to solve this is with protocol paths (if you're using clojure)

nathanmarz23:05:03

protocol path solution would be extensible to other types of nodes beyond Action and Condition

mac23:05:59

That might be even better, since I have several other record types.

nathanmarz23:05:27

there's examples of those on the README

mac23:05:09

Yeah, looked at those but it wasn't clear to me how to achieve my goal. Will look at them again.

nathanmarz23:05:04

(defprotocolpath SatisfactoryActionNodes)

(extend-protocolpath SatisfactoryActionNodes
  Action (continue-then-stay :children ALL SatisfactoryActionNodes)
  Condition [cond-filter :children ALL SatisfactoryActionNodes])

mac23:05:38

@nathanmarz That it is very elegant.