ref returns and properties

Andrei Alexandrescu SeeWebsiteForEmail at erdani.org
Mon Jan 26 13:56:17 PST 2009


Steven Schveighoffer wrote:
> "Andrei Alexandrescu" wrote
>> 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.
> 
> There are two possibilities that I can think of.
> 
> 1. ref return from get, which gets you part-way there.  You can still do 
> some useful things like which member you are returning getting calculated, 
> but it doesn't make the call to set when you assign to the property, or 
> allow calling get multiple times to return different values.

Yah, exactly. One thing I'm rather sad about is that certain containers 
won't be implementable that way, for example sparse vectors (with most 
elements zero). A sparse vector would want to return by value from 
head() and opIndex() (so it can return 0.0 most of the time) and would 
also want to have control over setting slots. So in brief, sparse 
vectors won't be supported naturally by our paradigm. They will still be 
supported, just not in a manner that makes them next to 
indistinguishable from dense vectors.

Lately I'm getting to think (sour grapes syndrome?) that probably that's 
a good thing. A sparse vector is very long - e.g. millions of items, and 
only has a few or a few hundred that are nonzero. It would be wasteful 
to ever iterate over the whole one million items; I'd rather use a 
custom algorithm that only "sees" the nonzero elements. It would be nice 
to have opApply work, but I guess I can live with that too.

> 2. Have a "property delegate", which is like a normal delegate, but contains 
> 2 functions.  Calling a function which takes such a delegate makes the 
> compiler generate such a delegate in the case where a simple lvalue is 
> passed.  You could signify it with the terms "lazy ref" in the function 
> signature.

Yah, crossed my mind too. With the third function in tow (the one that 
does the resource acquisition or whatnot) things are getting rather 
overweight and it starts looking like a full-fledged local class with a 
vtable and the works might be an option. Local classes have access to 
the frame pointer of their parent, so probably things can be arranged to 
work. But the cost of the whole operation becomes too high.


Andrei



More information about the Digitalmars-d mailing list