Choosing ref vs object is about the semantics of your type and also it's copying.
If your type represents an unique resource or instance for example a file handle, a database or socket connection or GPU memory, a tree node, a person, a game level. This is particularly true if the resource resource that cannot be copied but should be **referred** to. Otherwise if your object is _fungible_ (to use a finance term that mean any dollar bill is the same, any bag of 1kg of rice is the same) i.e. the only characteristic of the object is the value, use plain objects. For example, you have a distance A and distance B, to compare if they are equal, you only compare their value. Now you have Person A and Person B, they have a position, to compare if 2 persons are equal, you don't just compare their distance to an origin, 2 persons can be different while being at the same position. In short, Distance would be a value while Person would be a reference. Mutability is orthogonal from value vs reference and the fact that references do not require `var` to update their field is a limitation of the language (also called deep immutability, vs the current shallow immutability). (It would require write-tracking analysis or a borrow checker). The second reason to choose ref over plain object is when you want to implement an inheritance hierarchy and want to store inherited subtypes in the same container. I'd argue that in many cases object variants are superior unless you want this to be extensible by an user (so that that user can easily add their own derived classes). Note that the last part (adding new variant to an object by an external user) can be solved in Nim via macros. In fact I wrote my own class emulation for variants for my RayTracer: [https://github.com/mratsim/trace-of-radiance/blob/99f7d85d/trace_of_radiance/support/emulate_classes_with_ADTs.nim#L264-L268](https://github.com/mratsim/trace-of-radiance/blob/99f7d85d/trace_of_radiance/support/emulate_classes_with_ADTs.nim#L264-L268). The idea is that user use `registerSubType` and `registerRoutine` to add new subtypes and new functions and the library calls `generateClass` and `generateRoutines` at a choice place. Regarding the disadvantages of inheritance vs object-variants. * It's harder to track mutability of ref objects * They are not threadsafe, this will be improved with --gc:arc but in general plain values are always easier to deal with * They are slower, on current CPUs the biggest bottleneck is memory access, a ref object is a pointer which incur pointer indirection penalty. An object variant instead require a switch, but the latest CPUs branch predictor is very good (from the past 6 years) and the subtype branch is 100% predictable and so this is costless. (see [https://hal.inria.fr/hal-01100647/document](https://hal.inria.fr/hal-01100647/document) and this is about an interpreter with 200+ branches not an object with only a couple)
