Beginner and Rc () and also Arc()

Should beginners use Rc() and Arc() ?

Or it is better to avoid its for now ?

Well, it depends on why you're using them. In general, I would say that Rc<RefCell<..>> should only be used rarely, but using Rc on its own is pretty much always perfectly fine. (The difference is that you need RefCell to modify the shared value.)

1 Like

Experts should avoid Rc. Beginners should become experts. Don't worry too much and instead write some code. (Avoid unsafe far more.)

2 Likes

Using Arc or Rc is completely fine; the only problem is that it does come inherently with some restriction (its contents are no longer mutable unless you also use something like RefCell) which is why you should use Box whenever the additional capabilities of Rc aren't needed. So simply always use whatever works best for you and your use-case, and try to figure out / learn how to tell when Rc is or isn't helping.

Same goes for RefCell (or Rc<RefCell<…>>). Sure, there is also the general principle that code with shared mutability is harder to reason about, etc.. (and very minor performance impacts) but also, it's simply a bit less flexible in some ways: you cannot write a &RefCell<Foo<T>> -> &T function, and to deal with this, using RefCell often forces more use-cases of Rc in the contained data (i. e. as a field of Foo<T> because then you could do &RefCell<Foo<T>> -> Rc<T> instead, which does work), which in turn might force more usage of RefCell if the data needs to stay mutable. I. e. it can be somewhat infectious and code becomes more verbose... which is a good reason to avoid using it in cases where it wasn't needed in the first place.

1 Like

The reason of my asking is this video on yutube..

The Importance of Not Over-Optimizing in Rust

She says:
Beginners, to avoid painful things in rust
a. use owned vars
b. use clone()
c. compile as release
d. use rc() and arc()

I had believing Rc is for experienced devs..

1 Like

Rc is definitely used by experts, but the ways in which they are used by experts differ quite a lot from how new Rust users use Rc.

The issues that new users run into are best described as Rc/RefCell hell, and you can tell that you are in this situation by noticing that your codebase is littered with calls to borrow and borrow_mut.

Interestingly, Rc/RefCell hell pretty much always involves RefCell too. If you use only Rc, then you're probably doing something reasonable.

7 Likes

In past I had this opinion:

But seeing this video …

… I wonder if my p.o.v. is a pretty individual thing. I like to find solutions where unnecessary allocations are avoided (e.g. here) and then I sometimes find myself spending hours and hours on finding the optimal type signatures for my problem. A real time killer. It's fun but I see how this lowers my productivity, at least in the short term (though I learn a lot about Rust but this seems endless).

So using Rc, hmmmm… :thinking: I would probably only use it where ownership isn't clear, i.e. where a value is "owned" by several structs or locals. Adding Rc everywhere might make type signatures also a bit complex and difficult to overlook.

1 Like

Yes, you should use Arc.

There are many situations in Rust where Arc is legitimately needed, no matter whether you're an expert or beginner. For example for sharing data between non-scoped threads, in complex graph structures, or in caches.

Even in situations where Arc isn't strictly necessary, it's often fine to use it, because it's only a minor performance difference. Using Arc to reference data is often easier for beginners than using temporary loans (references).

Arc is fine to use wherever Rc is, but not the other way, so if in doubt, Arc is an easier choice.

2 Likes

That depends on your goal. If your goal is to get a deep understanding of the language, then avoiding Rc/Arc will be more helpful. There are situations where they are legitimately unavoidable, but learning to recognize those takes a lot of time and practice. In short, they are required when single ownership is impossible, but beginners tend to gravitate towards shared ownership when it is not required, or even is plain harmful. This is a consequence of the prevalence of garbage-collected languages, which make it easy to use shared ownership. However, most tasks can be accomplished within Rust's single ownership framework, even if the familiar solutions don't immediately apply.

If your goal is to solve a practical problem, then it is often better to optimize for delivery time, and in that sense Rc/Arc are indeed very helpful. They basically give you access to a poor man's garbage collector, with all the power it gives you (just note that cycles of references need to be handled manually with strategically placed Weak pointers, otherwise you will leak resources). This trades the problem of single ownership for a problem of reference cycles, multiple ownership and worse ergonomics, but those problems are generally more familiar to many people. Since Rust is designed around ownership and borrowing, the ergonomics of using reference counting are much worse: you will have to use a lot of ugly Arc<Mutex<T>> types, explicit cloning, borrowing and locking. This will likely leave a worse impression of the language, and you will be unable to leverage some of its more powerful feature, but as a short-term solution it may be preferable.

The optimum is likely somewhere in the middle. Try to follow the single ownership principles, but if you get in a tight spot it may be better to Arc and clone the issue away instead of spending hours or days on the problem. It is important to learn the proper use of the language, but it's also important to maintain your momentum and motivation towards the task and the language. By cloning your issues away you can prevent frustration and focus on the other parts of the language, and there is a lot to learn in Rust.

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.