Hi. I'm new to Rust and I'm having a lot of trouble understanding how to use cells well, among other things. I'm implementing a quick Scheme interpreter and that's gone okay: I'm using this GC library which provides a Gc
type, which is like Rc
but garbage collected. My Lisp Object
s are just an enum
where any internal fields are Gc
s. When I call functions with Lisp objects they get a &Gc<Object>
, and if they return a Lisp object they return a Gc<Object>
to indicate that there's a new way to get at the underlying object. I think I'm thinking about this little of the reference semantics correctly, and it seems to be the same reference discipline used by another much more sophisticated Scheme in Rust I found.
I can use the match
operator to pick objects apart when necessary. For example, my eval
looks like this:
pub fn eval(form: &Gc<Object>, env: &Gc<Object>) -> EvalResult {
match *form.borrow() {
Object::Cons {car: ref op, cdr: ref args} => {
combine(&eval(op, env)?, args, env)
}
...
}
}
The problem comes in when I try to make a mutable field. The GC library says to wrap in GcCell
, which is like RefCell
. So for example I would have
enum Object {
Cons { car: GcCell<Gc<Object>>, cdr: GcCell<Gc<Object>> },
... }
Now in this eval
for example, op
and args
will no longer be &Gc
s, they will be &GcCell<Gc>
s. GcCell
's borrow
, like the standard RefCell
, returns a GcCellRef
(resp. Ref
) instead of an actual reference, so I can't just call borrow
. To get a &Gc
out of &GcCell<Gc>
, for passing around, all I've managed to come up with is &*op.borrow()
, which I think borrows the underlying Gc
from the cell, then dereferences that GcCellRef
(which copies, maybe? which I don't want if I can avoid it?) to get a Gc
, and then I take a reference to that. That's pretty weird to write everywhere, and doesn't seem normal. I can't hide it away in a function, either, since the function would return a reference to the temporary Gc
.
I suspect there's something deeply wrong with my thinking. Should I just be using GcCellRef
everywhere instead of actual references? Or define my own Ref
-like thing? Any advice would be appreciated. I'm sorry if using Gc
makes it needlessly confusing, but I used to just use Rc
and I think I'd have the same problem with RefCell
.