Properties: a.b.c = 3

Jarrett Billingsley jarrett.billingsley at gmail.com
Wed Jul 29 06:10:07 PDT 2009


On Wed, Jul 29, 2009 at 1:08 AM, Daniel Keep<daniel.keep.lists at gmail.com> wrote:
>
>
> Jarrett Billingsley wrote:
>> On Tue, Jul 28, 2009 at 10:33 PM, Walter
>> Bright<newshound1 at digitalmars.com> wrote:
>>> The issue is what if b is a property, returns a temporary object, and that
>>> temp's .c field is uselessly set to 3?
>>
>> So, the issue is that 'a.b()' returns a struct by value.  Such return
>> values should always be considered rvalues.  Furthermore,
>> 'rvalue.field' should also only yield an rvalue.  Therefore, 'a.b.c =
>> 3' should be flagged by the compiler as being as nonsensical as "5 =
>> x".
>>
>> The compiler would flag this as an error, and the solution would of
>> course be to make a.b's return value by reference instead.
>
> Problem: what if .b is computed?  Take .length as an example; the setter
> MUST be invoked when the length changes, or the stored value won't have
> any bearing on the actual number of elements being stored.

That's not the issue at hand.  The issue is that the compiler accepts
no-effect modifications of temporary values as valid statements.
There is no setter being invoked here, nor should there be.

Or should there?  In the face of a value type, should the compiler
rewrite this code as

auto t = a.b();
t.c = 3;
a.b = t;

?  The last line of the rewrite is unnecessary if a.b() returns a
reference type or a byref struct.  But is this what people would
expect to happen?

> Returning refs only works if the property is just pretending to be a
> field; in which case the correct solution is to use a field.

Not entirely; you can (for some value of 'can') return a struct that
has overloaded opAssign to do nontrivial setters.  But that's kludgey
and C++-y.



More information about the Digitalmars-d mailing list