Why should each `Applier` only work either bottom ...
# compose
m
Why should each
Applier
only work either bottom up or top down but never both?
j
Because otherwise you'll add nodes twice to their parents
It's the same tree traversal, you're just choosing in which direction to build the tree
In Redwood we actually use both callbacks and we add some nodes while going down and others while going up https://github.com/cashapp/redwood/blob/trunk/redwood-compose%2Fsrc%2FcommonMain%2Fkotlin%2Fapp%2Fcash%2Fredwood%2Fcompose%2FWidgetApplier.kt#L88-L112
m
@jw I don’t get it.
insertBottomUp
and
insertTopDown
are two separate methods. Why can’t an applier let the caller decide how to build a tree? Why should every applier make either a no-op?
let the caller decide how to build a tree
Isn’t this what you’re doing in the code you’ve linked too?
j
The caller is composable functions
The tree corresponds to the implicit call graph (which is always a tree)
m
@jw I appreciate the explanation but unfortunately I’m still immensely confused. My understanding is that
@Composable
functions emit data that can be interpreted as a tree to the injected
Composer
, and it’s the
Composer
that uses a given
Applier
. What’s wrong with an implementation of
Applier
that implements both
insertBottomUp
and
insertTopDown
, so each
Composer
can choose which insertion method to use?
j
Because then each node would get added twice
You can either add the nodes to the tree when walking down each branch or when coming back up
m
But doesn’t yours also implement both? Is that on purpose?
And who calls both methods? The
Composer
?
j
Yes, the comments indicate why. We add some nodes when walking down and others when walking up
m
The
Composer
starts at the root, adds nodes top down while traversing down, and then also always comes back up adding nodes bottom up?
1. (going down)
root
2. (going down)
root
->
A
3. (going down)
root
->
A
->
B
4. (coming back up)
root
->
A
->
X
->
B
5. (coming back up)
root
->
A
->
Y
->
X
->
B
6. (coming back up)
Z
(new root) -> old
root
->
Y
->
X
->
B
Like this?
j
The same nodes are visited in both directions. So if you have
A { B { C() } }
, the calls would be root/down/A, A/down/B, B/down/C, B/up/C, A/up/B, root/up/A
(I can't format it the same way you did on mobile)
m
@jw An
Applier
takes the nodes that exist at a given point in time, and traverses down and back up the tree to possibly add new nodes without visiting those new nodes during the traversal?
j
I'm not sure what you mean by "without visiting". The Composer has recorded all of the changes to the SlotTable (which maintains the nodes). Once the recomposition was successful those changes are applied to the tree using the
Applier
by moving its current node to the parent, and then invoking any of the manipulation callbacks (insert, move, remove).