I realized that properties are not a complete model for actual data. The current conventional wisdom about properties goes like this (T is some type):

class Host
{
    property prop
    {
        T get() { ... }
        void set(T value) { ... }
    }
}

If T is e.g. an int, it all works nicely. Now consider T is a highly-structured piece of data that holds resources. In that case we want to make sure T is not copied unwittingly such that the resource is managed properly. This means that T has a copy constructor and a destructor.

For such cases, extensive experience with C++ has shown that two primitives are essential: move and swap.

void move(ref T src, ref T dst);
void swap(ref T lhs, ref T rhs);

Move takes the guts of src, puts them in dst, and then clears src effectively relieving it from any resource. Swap exchanges the guts of src and dst without any extra resource copying.

Now if "prop" were a classic data, swapping host1.prop and host2.prop is a piece of cake (that is realized inside std.algorithm. Look it up, the implementation has quite a few interesting quirks!)

But if "prop" is a property with get and set, everything falls apart. Properties effectively hide the address of the actual data and only traffic in values. That's often good (and sometimes even the only possibility in the case of properties computed on-the-fly), but this abstraction effectively makes resource-conserving move and swap impossible.

I noticed this problem when dealing with ranges. The .head() function, if it returns a value, cannot be swapped/moved. Same applies to opIndex when implemented as a value property (via the opIndex/opIndexAssign tandem).

What to do? I'd like to refine the notion of property such that moving properties around is possible, without, however, complicating their interface too much.


Andrei

Reply via email to