Hi, @MilesCranmer, I’m opening this as a separate thread so the other thread can focus on your thoughts about a Rust-like borrow checker for Julia.
I made an example of a Node
type with a splice
method that replaces a sub-tree of the Node
with a different sub-tree. If I’m not mistaken, it avoids copying the whole tree over. As @bertschi mentioned, you only need to rebuild the path to the node that is changed—the other sub-trees are unchanged.
Here’s the code:
struct Node
x::Int
l::Union{Node, Nothing}
r::Union{Node, Nothing}
end
# `path` is a boolean vector. A `false` means go left and
# a `true` means go right.
function splice(node, new_node, path)
_splice(node, new_node, path, 1)
end
function _splice(node, new_node, path, i)
go_right = path[i]
i += 1
if i > length(path)
if go_right
Node(node.x, node.l, new_node)
else
Node(node.x, new_node, node.r)
end
else
if go_right
Node(node.x, node.l, _splice(node.r, new_node, path, i))
else
Node(node.x, _splice(node.l, new_node, path, i), node.r)
end
end
end
Here’s a small example:
julia> t = (
Node(1,
Node(2,
Node(4,
nothing,
nothing
),
Node(5,
nothing,
nothing
)
),
Node(3,
nothing,
nothing
)
)
)
Node(1, Node(2, Node(4, nothing, nothing), Node(5, nothing, nothing)), Node(3, nothing, nothing))
julia> s = (
Node(6,
Node(7,
nothing,
nothing
),
Node(8,
nothing,
nothing
)
)
)
Node(6, Node(7, nothing, nothing), Node(8, nothing, nothing))
julia> r = splice(t, s, [false, true])
Node(1, Node(2, Node(4, nothing, nothing), Node(6, Node(7, nothing, nothing), Node(8, nothing, nothing))), Node(3, nothing, nothing))
And a small benchmark:
julia> using Chairmarks
julia> path = [false, true];
julia> @be splice(t, s, path)
Benchmark: 3968 samples with 946 evaluations
min 17.354 ns (2 allocs: 64 bytes)
median 20.304 ns (2 allocs: 64 bytes)
mean 25.512 ns (2 allocs: 64 bytes, 0.20% gc time)
max 3.832 μs (2 allocs: 64 bytes, 98.99% gc time)
Admittedly, it’s a very small benchmark. Maybe you can generate a bigger example.
I don’t know if this is fast enough for you, or if this is similar to what you’ve tried in the past.