Reference capabilities make it safe to both pass mutable data between actors and to share immutable data amongst actors. Not only that, they make it safe to do it with no copying, no locks, in fact, no runtime overhead at all.

Passing

For an object to be mutable, we need to be sure that no other actor can read from or write to that object. The three mutable reference capabilities (iso, trn, and ref) all make that guarantee.

But what if we want to pass a mutable object from one actor to another? To do that, we need to be sure that the actor that is sending the mutable object also gives up the ability to both read from and write to that object.

This is exactly what iso does. It is read and write unique, there can only be one reference at a time that can be used for reading or writing. If you send an iso object to another actor, you will be giving up the ability to read from or write to that object.

So I should use iso when I want to pass a mutable object between actors? Yes! If you don’t need to pass it, you can just use ref instead.

Sharing

If you want to share an object amongst actors, then we have to make one of the following guarantees:

  1. Either no actor can write to the object, in which case any actor can read from it, or
  2. Only one actor can write to the object, in which case other actors can neither read from or write to the object.

The first guarantee is exactly what val does. It is globally immutable, so we know that no actor can ever write to that object. As a result, you can freely send val objects to other actors, without needing to give up the ability to read from that object.

So I should use val when I want to share an immutable object amongst actors? Yes! If you don’t need to share it, you can just use ref instead, or box if you want it to be immutable.

The second guarantee is what tag does. Not the part about only one actor writing (that’s guaranteed by any mutable reference capability), but the part about not being able to read from or write to an object. That means you can freely pass tag objects to other actors, without needing to give up the ability to read from or write to that object.

What’s the point in sending a tag reference to another actor if it can’t then read or write the fields? Because tag can be used to identify objects and sometimes that’s all you need. Also, if the object is an actor you can call behaviours on it even though you only have a tag.

So I should use tag when I want to share the identity of a mutable object amongst actors? Yes! Or, really, the identity of anything, whether it’s mutable, immutable, or even an actor.

Reference capabilities that can’t be sent

You may have noticed we didn’t mention trn, ref, or box as things you can send to other actors. That’s because you can’t do it. They don’t make the guarantees we need in order to be safe.

So when should you use those reference capabilities?

  • Use ref when you need to be able to change an object over time. On the other hand, if your program wouldn’t be any slower if you used an immutable type instead, you may want to use a val anyway.
  • Use box when you don’t care whether the object is mutable or immutable. In other words, you want to be able to read it, but you don’t need to write to it or share it with other actors.
  • Use trn when you want to be able to change an object for a while, but you also want to be able to make it globally immutable later.