clj-commons / rewrite-clj

Rewrite Clojure code and edn
https://cljdoc.org/d/rewrite-clj
MIT License
592 stars 55 forks source link

Normalize terminology for root and top #190

Open mainej opened 2 years ago

mainej commented 2 years ago

Problem/Opportunity

The idea of adding a helper function top has been proposed several times: #189, #125, #149 and perhaps others. Before making a decision about that feature, I think it would help to clarify what the word "top" means, especially because it currently has a slightly different meaning in rewrite-clj than it does in the wider Clojure community.

In general, in rewrite-clj, "top" or "top-level" refers to the :forms node. In the rest of the Clojure community, "top-level" generally refers to the children of the :forms node.

Proposed Solution

I can imagine several ways to address this ambiguity in terminology. My personal preference would be to use the word "root" to mean the :forms node, reserving the word "top" for its children.

(defn root? [loc]
  (identical? :forms (z/tag loc)))

(defn top? [loc]
  (root? (z/up loc)))

(defn to-root
  "Returns the loc of the root `:forms` node."
  [loc]
  (z/find loc z/up root?))

(defn to-top
  "Returns the loc for the top-level form above the loc, or the loc itself if it
  is top-level, or nil if the loc is at the `:forms` node."
  [loc]
  (z/find loc z/up top?))

I'm not sure whether these need variations with different whitespace/comment handling, and if so, whether that should mean parallel functions to-top*, etc., or whether these functions should have a different arity that accepts the navigation function. The second option might be a little odd, since it would permit nonsensical code like (z/to-root zloc z/down).

Alternative Solutions Several other approaches are possible. It could simply be a review of the documentation and Issues, clarifying when necessary. Or other terminology might be preferable—"root" is an arbitrary choice.

borkdude commented 2 years ago

I think root? makes sense. For top-level nodes, maybe top-level? or more explicit? top? would also be ok with me.

lread commented 2 years ago

Interesting. I'm all for defining terms and making things clearer!

One thing to keep in mind is that rewrite-clj is based on Clojure's zipper implementation which in turn is based on Huet's zipper.

Clojure's zip docstrings seem to use the word "top" as an equivalent to "root".

A bit confusing, to me at when first learning anyway, is that it also has fn root which returns the resulting ingested structure. I think a name like root-node would have been clearer to me. But that could just be me.

We could also look into terminology used in Huet's paper on zippers to see if he had clear definitions. A quick search shows "top" used in source snippets and "root" used in text.