-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Get rid of special TreeNodes #8663
Comments
Let me open a PR once #8653 landed. |
Another common pattern in Rust is to capturing state in a closure rather than an explict payload -- perhaps that idea is also worth considering |
We have also observed the complex API and different implementation approaches of TreeNode. I'm not sure if this is the right place to share these but, let me share our findings and a simple POC of how we can have a new trait providing a simpler and more understandable API: Since the general approach in Datafusion tree structs involves having the children nodes within the self node, a pure There are also some unused functionalities and outcome types in general, so I think that a more simple API is enough usually. I scribbled a little and came up with something like this, sharing it here in case it's useful.
I don’t know yet how this design can be integrated with the existing TreeNode, but in many places, such a design makes things easier and more understandable. |
I think think this is partly the same idea I was suggesting in 1. of #7942. The main point there was that the closures change from Where I see some differences is the return type of our closures. Your code snipett shows So basically here is the trait TreeNode_v2: Sized {
fn transform_children<F>(&mut self, f: &mut F) -> Result<TreeNodeRecursion>
where
F: FnMut(&mut Self) -> Result<TreeNodeRecursion>;
fn transform(&mut self, f_down: &mut F, f_up: &mut F) -> Result<TreeNodeRecursion>
where
F: FnMut(&mut Self) -> Result<TreeNodeRecursion>,
{
// Apply `f_down` on self.
f_down(self)?
// If it returns continue (not prune or stop or stop all) then continue
// traversal on inner children and children.
.and_then_on_continue(||
// Run the recursive `transform` on each children.
self
.transform_children(&mut |c| c.transform(f_down, f_up))?
// Apply `f_up` on new self.
.and_then_on_continue(|| f_up(self)))?
// Applying `f_down` or `f_up` on self might have returned prune, but we
// need to propagate continue.
.continue_on_prune()
}
} Regarding
I totally aggree. Lastly, in this particulat issue I wanted to see if there is a way to get rid of those special trees. It seems unecessary to create those thees and I found it very hard to follow how additonal payload is propagated down/up. In #8664 I removed |
Thanks @peter-toth for your detailed explanation
I hadn't thought deeply about the return type, but your suggestion makes a lot of sense.
I wasn't aware of I will review #8664 and write my new thoughts there. I believe we will find the most appropriate solution 🚀 |
Is this ticket still tracking anything I wonder (or is it now covered by #8913 🤔 ) |
I think we can close this issue as #8817 reduced the number of |
Thanks again @berkaysynnada and @peter-toth -- the TreeNode API is looking quite good these days |
Is your feature request related to a problem or challenge?
Currently there are many special
TreeNode
trees in DataFusion so as to carry additional information needed for tree transformations. These special trees are a bit cumbersome as they need to implementTreeNode
functions (apply_children()
,map_children()
).Describe the solution you'd like
I'm suggesting to add
TreeNode.transform_with_payload()
,TreeNode.transform_down_with_payload()
andTreeNode.transform_up_with_payload()
to propagate down/up additional information duringTreeNode
transformation.Please see 4. in #7942 and its POC implementation.
Describe alternatives you've considered
No response
Additional context
No response
The text was updated successfully, but these errors were encountered: