AbstractTrees - iterating without a tree

If I have a tree, I can use AbstractTrees.jl to iterate it. All I needed was to define

import AbstractTrees as AT
AT.children(n::MyNode) = ...

Great!

But often times I don’t have a tree and I don’t want to build it in memory. Instead I have an object that we could consider the tree root, and I have operations that I can do to mutate the object which lead me to other nodes. For motivation, imagine that you want to walk the tree in a board game: you don’t want to have a copy of the board for every position that you’re considering, you just want to be able to iterate thru the positions (so you can hash them and score them). Question: can I get AbstractTrees.jl to mutate my object instead of moving from node to node?

Reading the docs I learned about an object called a TreeCursor. A cursor is an object that ATs.jl uses internally to navigate a tree. According to the docs:

Tree iteration algorithms rely on TreeCursor objects. A TreeCursor is a wrapper for a tree node which contains all information needed to navigate to other positions within the tree. They themselves are nodes of a tree with the StoredParents and StoredSiblings traits.

So I thought, maybe instead of building a tree and passing it into ATs.jl I can build a cursor directly, and pass that? From the docs all I need to do is, in addition to AT.children also implement some traits plus the functions AT.parent and AT.nextsibling.

I’d like to hear from either someone who contributed to this library, or is experienced with it, whether this is a use-case (although not one covered by the documentation) or whether I’m missing something - and if the latter, is there a way to use ATs.jls if I don’t want to build a tree? The reason why I’m not super confident this idea might make sense is that, while the AT.parent case works great (mutate my object to go up one level and then return itself), it’s not clear how the AT.children would work - I could return an object with getindex defined on it, but it’s not clear that ATs won’t do something that will break this - for example call AT.children, make a copy, access the result to get one child node, call AT.nextsibling on it, then access a different of element of its AT.children copy.