0:00
/
0:00

Refcells, and Binary Trees in Rust

Not even Microsoft Copilot could write a program to my specifications.

Code on GitHub: https://github.com/caveofprogramming/rust/

RefCell

RefCell (std::cell::RefCell) is another kind of smart pointer.

It implements the “interior mutability” pattern. This means that you can mutate the contents of a RefCell using an immutable reference.

Borrowing rules with RefCell are enforced at runtime, not compile time.

RefCell provides two functions that allow you to get references to its contents: borrow() and borrow_mut().

In the following example, I wrap an integer in a RefCell, print it using borrow() and alter it using borrow_mut().

My Descent Into Madness

At this point I found myself facing a difficult question: what is this actually for?

I read somewhere that it might be useful for implementing tree or other structures, where you want to be able to alter the nodes.

You might use Rc to implement multiple ownership of the nodes, so that one node can be in multiple places and still get cleaned up at the right time.

But Rc does not allow you to mutate its contents, so you can wrap a RefCell with an Rc.

This sounds fine and I was able to get Microsoft Copilot to implement such a program (I couldn’t quite manage it myself), but the unsatisfactory thing is that the resulting API isn’t very clean.

It ends up being necessary to call borrow methods on the nodes before calling their insert methods.

When I tried to get Copilot to implement something more to my liking, including nodes that contain strings, it couldn’t seem to manage it, producing code over and over again that just didn’t compile.

The Problem

Part of the problem, I realised, was that I wasn’t clear about what I actually wanted. I can’t have nodes that are owned by variables in main() but then somehow also have multiple owners within some structure, unless those nodes are actually created as Rc smart pointers.

No matter what I try, it becomes necessary to expose smart pointer methods outside of my desired API.

Another problem is, if nodes in a tree can appear at different points in a tree, those nodes will also have pointers to other nodes that are repeated within the tree, and potentially you’ll create an infinite recursive tree.

Solution, Sort Of

Eventually I came up with the program outlined in the video, which you can also find on GitHub.

This consists of nodes formed from Data structs, connected by Connector structs.

It’s possible to connect them into a kind of triangle, or loop, where the last in the chain connects to the first.

Because RefCell is used to refer to the nodes, they can be seamlessly swapped out, even though immutable Rc smart pointers are used to refer to them.

Discussion about this video

User's avatar