[swift-users] Are value semantics really appropriate in a diagramming app?

Rick Mann rmann at latencyzero.com
Tue Aug 2 16:23:43 CDT 2016

> On Aug 2, 2016, at 13:07 , Dave Abrahams via swift-users <swift-users at swift.org> wrote:
> on Mon Aug 01 2016, Rick Mann <swift-users-AT-swift.org> wrote:
>>> On Aug 1, 2016, at 19:18 , Jack Lawrence <jackl at apple.com> wrote:
>>> Jens: Why? There are significant benefits to value semantics for
>>> this type of problem, for the reasons laid out in the WWDC
>>> videos. It would be helpful to know why you disagree in this
>>> case—maybe there are solutions to the issues you’re thinking of.
>>> Rick: I’d think that value semantics would be the right choice
>>> here. When you do a mutation, you would copy the state of the entire
>>> diagram. It should be efficient via COW, but if not you can
>>> implement you own more fine-grained COW types with
>>> isUniquelyReferenced(). This would allow you to easily support
>>> things like undo.
>> The more I consider this, the more I think value semantics won't work
>> for me. I think, to take advantage of the easy undo feature, my entire
>> model *must* be implemented with value semantics.
> That certainly helps.  You could introduce an explicit copy operation
> to get around the use of classes, but that can get very messy.
>> But my model has implicit reference semantics: multiple instances of a
>> part can share a PartDefinition; it is intended that if the
>> PartDefinition changes, all the referencing instances get the
>> change. 
> That is definitely a reference.  However, there are lots of ways to
> represent references such that the entire model still has value
> semantics.  Reference semantics, in the broadest sense, are everywhere:
> as soon as you have an array and an integer, you have reference
> semantics.  The problem with using classes is that they introduce
> reference semantics *implicitly* and *prolifically*.
> So, for example, if you are implementing a model and you want to
> represent a selection as a separate data structure, then you'll need to
> give every selectable element some kind of id, so you can store the ids
> there. One way to do that is to store all your elements in an array in
> your model, and use the index into the array as the id.  Then when one
> element needs to refer to another element, it stores the ID of that
> element.
> [Aside: one of the simplest and most efficient representations of a
> generalized graph structure is `[[Int]]`, which has value semantics.
> Each element of the outer array corresponds to a vertex, and each
> element an inner array represents the target of that vertex's outgoing
> edges]
> The most obvious thing you don't get from this kind of arrangement is
> automatic lifetime management: an element doesn't disappear just because
> you've stopped referring to it.  Whether that's appropriate for your
> application or not is a question for you to answer.  
> You can selectively recreate as much of the implicit behavior of classes
> as you like, e.g. storing reference counts to recreate automatic
> lifetime management and/or threading a free list through the array to
> maintain ID stability, but of course at some point it becomes silly.
> Where your particular application falls in this spectrum is for you to
> say.  The fact that there's a component of reference semantics in your
> model doesn't mean you can't use value types, and the fact that using
> value types has some awesome benefits doesn't mean you can't use
> classes.  Weigh the tradeoffs and make an informed choice.
>> There are additional situations in which reference semantics are at
>> play, as well: a PartDefinition can have one or more labels, but each
>> instance can specify the relative location of the label for that
>> instance. So, there is struct that contains a position and a reference
>> to the label in the PartDefinition. But if the contents of the label
>> changes, all the instances need to see that change.
>> I don't think I get to take advantage of value semantics, and it makes
>> me wonder if any typical, non-trivial model's object graph really has
>> no reference semantics.
> Some do, but many-to-one relationships are an important concept, and
> many applications need to represent them somehow.  I've personally found
> that most such relationships are best expressed explicitly, which allows
> me to preserve value semantics of the whole system. YMMV, of course.

Hmm. Seems there's a need in the language for expressing exactly this kind of thing: explicit reference semantics. I sure don't want to manage that all on my own.

Rick Mann
rmann at latencyzero.com

More information about the swift-users mailing list