akhudek / zip-visit

zip-visit
MIT License
57 stars 10 forks source link

Include loc in `(v dir node state)`? #5

Open refset opened 8 years ago

refset commented 8 years ago

As per the title, would you accept a PR to modify visit-node so that loc is passed to the visitors i.e. (v dir loc node state)?

On another note, (z/node loc) is immediately repeated on line 22.

Great library :+1:

refset commented 8 years ago

On further thought I'm not sure I can use zip-visit how I was intending, so the question above probably isn't worth considering after all.

In case you wondered though: what I really need is a notion of down-state and right-state which are independent of the existing (next-)state but I can't see how to bend zip-visit to achieve that without recursion ...unless you have any good ideas?

akhudek commented 8 years ago

I'm away for a few days, but let me think on it when I get back. A concrete example of what you're trying would help. On Jun 24, 2016 7:38 AM, "Jeremy Taylor" notifications@github.com wrote:

On further thought I'm not sure I can use zip-visit how I was intending, so the question above probably isn't worth considering after all.

In case you wondered though: what I really need is a notion of down-state and right-state which are independent of the existing (next-)state but I can't see how to bend zip-visit to achieve that without recursion ...unless you have any good ideas?

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/akhudek/zip-visit/issues/5#issuecomment-228324039, or mute the thread https://github.com/notifications/unsubscribe/AAJAsaCbTMkifz38qlFZLyrDCLd05yZ5ks5qO8HDgaJpZM4I9CuI .

refset commented 8 years ago

Okay, this is approximately what I am currently doing, without any use of zippers (I'm using datascript):

(let [visit (fn visit [db
                  node
                  {:keys [initial-right-state get-down get-right down-state right-state next-state] ;; :break :cut
                   :as state}
                  [& visitors]]
              (as->
                ((first visitors) db node state) ;; currently only works with a single visitor, implicitly :pre
                m
                (if-let [down* (and (not (:cut (:next-state m)))
                                    (not (:break (:next-state m)))
                                    (get-down db node))]
                  (assoc m :next-state
                         (:next-state (visit db
                                             down*
                                             (merge
                                               state
                                               {:next-state (:next-state m)
                                                :down-state (:down-state m)
                                                :right-state initial-right-state})
                                             visitors)))
                  m)
                (if-let [right* (and (not (:break (:next-state m)))
                                           (get-right db node))]
                  (assoc m :next-state
                         (:next-state (visit db
                                             right*
                                             (merge
                                               state
                                               {:next-state (:next-state m)
                                                :right-state (:right-state m)})
                                             visitors)))
                  m)
                ;; :post not needed, not implemented
                ;; :in not needed, not implemented (needs get-up, remember that visitor can't replace the loc)
                ))]
(visit db 
        my-root-node
        {:get-down downfn
        :get-right rightfn
        :next-state {}
        :down-state {}
        :right-state {}
        :initial-right-state {}}
        [ visitorfn ]))

I managed to - for the most part - figure out a way to fit my datascript structure into clojure.zip/zipper but it's not pretty. If I could adapt the above to use loop & recur then I suppose I wouldn't need zip-visit at all but I don't see a way to do that either.

(sorry the indentation isn't perfect, I'm not sure of the easiest way to fix it...!)

flipmokid commented 7 years ago

I'd love to be able to access the loc of the node in the tree (either by extra param or meta on the node). I'm using this library to work on SQL ASTs and Relational Algebra trees. One of the steps is to verify syntactically that the SQL AST is correct. This involves a) checking attributes exist in the context, b) attributes have the correct types when used with operators such as SUM and c) filling in table names for columns which don't define them (e.g. SELECT id FROM x => SELECT x.id FROM x).

A and B is best done by modifying the tree with the schema in the FROM section, check all attributes exist in the WHERE section and check all attributes exist in the SELECT section. Unfortunately doing this means that C is difficult to do as the tree has been modified away from the original AST. If I could access the loc, store it in the state of the tree then if the first syntactic pass is okay I could do a second pass over the original ast and fill in the table references using the state.

What do you think?

akhudek commented 7 years ago

I've had a lot of requests for this, so it seems like a good idea. Want to take a shot at a PR for it?