Then I extend from that class to all subclasses and that allows me to do trees like this.
let float = new Float()
let math = new Math()
let rect = new Rectangle()
float
.connect(math)
.connect(rect)
Now I'm trying to do something similar in Rust and I realized that it was a bit harder than I thought.
I've tried to do it with RefCells but here I have the problem because of the &self connect which makes Rc::new(RefCell::new(self) to not work because it doesn't expect a reference.
I also tried to do it without cells but this is as far as I got and when I tried to introduce the mutation part there where so many lifetime issues I didn't know where to start.
Don't try to program javascript in rust, you are in for a rough time if you do. I'd give this blog a read, it's short and informative, and you are making mistakes 3 and 6.a on it.
To implement a node graph like this you need to use an Rc<RefCell<dyn Node>> combo. It's extremely difficult and awkward, as you have found out, and even if you do succeed, you will likely run into reference cycles. Since rust doesn't have a gc, that means you will likely leak large chunks of memory.
If you would like a graph, use a proper graph type. It'll be much easier than whatever you're trying to do here. If you need a tree, you can get away with fairly simple struct/enum combo:
enum NodeType{
Rect, //any variant associated data can go here
Triangle,
}
struct Node{
variant: NodeType,
children: Vec<Node>, //any data shared between all nodes goes here
}
What I’m going for is a node tree for graphics, skia in this case.
I’ve built it with javascript with canvas and modeled the api the same way the web audio api works.
So basically when the canvas node requests a draw it triggers get through the tree to evaluate math nodes and animation timelines and stuff like that.
So every node will do different things before it returns a float.
From your answers I take it I need to do it in a different way for Rust then.
I thought the principle was quite simple though, a node can have other nodes in it and be part of other and a get() in the node will trigger get() in the nodes it holds
You should consider having one large collection of all of the nodes, then using indexes or ids to look up their neighbours. This usually works pretty well.
This results in a cyclic ownership structure, which is incompatible with the single-owner principle of Rust.
If you only want a tree, then you don't need any reference counting. You can just have Boxes or a Vec tor of children, which you can then borrow mutably as needed. Trees lend themselves quite naturally to Rust's single ownership model.
Yeah, but that was the thing the question was about.
I wasn’t able to set it up so that I was able to mutate the node passed to connect, in this case passing the self into connections of this node.
Then returning that node so I can chain it.
And have that as a trait that all nodes can implement.
Also when the lowest node runs get it will run get recursively and when get is runned inside a node the return from its parent should be stored inside the node so the get is mutating as well