View mode: basic / threaded / horizontal-split · Log in · Help
February 06, 2009
Re: property syntax problems
Robert Jacques Wrote:

> On Thu, 05 Feb 2009 06:55:46 -0500, Alex Burton <alexibu@mac.com> wrote:
> 
> > Hi,
> >
> > I just found a bug that comes out of the property syntax.
> >
> > The property syntax is great in that it allows a smooth transition from  
> > simple code dealing with public member variables to the use of  
> > interfaces without needing to update the client code.
> > i.e. A.bob = 1 can stay as A.bob = 1 when bob changes from being an int  
> > to being void A::bob(int i)
> > instead of changing to A.bob(1).
> >
> > But this can introduce the bug I show below.
> >
> > Proposal :
> > If the temporary returned by the property syntax getter function is  
> > modified, then the corresponding setter function needs to be called with  
> > the temporary as argument.
> >
> > struct A
> > {
> >       int i;
> >       int j;
> > };
> >
> > class B
> > {
> >   A mA;
> > public:
> > 	A a() { return mA; }
> > 	void a(A a) { mA = a; }
> > };
> >
> >
> > int main()
> > {
> >      B b;
> >      b.a.j = 10;     // error b.a is a temporary.
> > }
> 
> This isn't a bug, it's a feature. What you wanted to use were ref returns  
> (see http://www.digitalmars.com/d/2.0/function.html )
> ref A a() { return mA; }


Using
ref A a() { return mA; }
requires us to have a member variable mA ( which is actually there in the example).
One of the reasons for using the setter and getter functions instead of the raw member variable is that there is not actually a member variable. For example:
A a()
{
    Dataset ds = mDatabase.Execute("SELECT A,B FROM TABLE");
    return A(ds[0][0],ds[0][1]);
}

void a(A a)
{
    mDatabase.Execute(format("INSERT %d,%d INTO TABLE;",a.i,a.j));
}

The only way I can see to handle this correctly is to use my proposal above.

This could be a really valuable feature in D if correctly implemented.
Being able to transparently change from a member variable in a struct to getters and setters on a struct to getters and setters on a class and in reverse order is really powerful and allows code to evolve in a much more fluid way.

Alex
February 06, 2009
Re: property syntax problems
On Thu, 05 Feb 2009 20:26:03 -0500, Alex Burton <alexibu@mac.com> wrote:

> Robert Jacques Wrote:
>
>> On Thu, 05 Feb 2009 06:55:46 -0500, Alex Burton <alexibu@mac.com> wrote:
>>
>> > Hi,
>> >
>> > I just found a bug that comes out of the property syntax.
>> >
>> > The property syntax is great in that it allows a smooth transition  
>> from
>> > simple code dealing with public member variables to the use of
>> > interfaces without needing to update the client code.
>> > i.e. A.bob = 1 can stay as A.bob = 1 when bob changes from being an  
>> int
>> > to being void A::bob(int i)
>> > instead of changing to A.bob(1).
>> >
>> > But this can introduce the bug I show below.
>> >
>> > Proposal :
>> > If the temporary returned by the property syntax getter function is
>> > modified, then the corresponding setter function needs to be called  
>> with
>> > the temporary as argument.
>> >
>> > struct A
>> > {
>> >       int i;
>> >       int j;
>> > };
>> >
>> > class B
>> > {
>> >   A mA;
>> > public:
>> > 	A a() { return mA; }
>> > 	void a(A a) { mA = a; }
>> > };
>> >
>> >
>> > int main()
>> > {
>> >      B b;
>> >      b.a.j = 10;     // error b.a is a temporary.
>> > }
>>
>> This isn't a bug, it's a feature. What you wanted to use were ref  
>> returns
>> (see http://www.digitalmars.com/d/2.0/function.html )
>> ref A a() { return mA; }
>
>
> Using
> ref A a() { return mA; }
> requires us to have a member variable mA ( which is actually there in  
> the example).
> One of the reasons for using the setter and getter functions instead of  
> the raw member variable is that there is not actually a member variable.  
> For example:
> A a()
> {
>      Dataset ds = mDatabase.Execute("SELECT A,B FROM TABLE");
>      return A(ds[0][0],ds[0][1]);
> }
>
> void a(A a)
> {
>      mDatabase.Execute(format("INSERT %d,%d INTO TABLE;",a.i,a.j));
> }
>
> The only way I can see to handle this correctly is to use my proposal  
> above.
>
> This could be a really valuable feature in D if correctly implemented.
> Being able to transparently change from a member variable in a struct to  
> getters and setters on a struct to getters and setters on a class and in  
> reverse order is really powerful and allows code to evolve in a much  
> more fluid way.
>
> Alex

Alex, this looks like you want to use proxy structs/objects. Remember each  
of the following are equivalent:

b.a.j = 10;
<=>
(b.a).j = 10;
<=>
auto c = b.a;
c.j = 10;

And that last case is a kinda tricky.

Also, the x.y.z = 10 not doing anything when y is a struct from your other  
post is a well known issue is all languages that have POD struct (As far  
as I know). The solution is to move x.y to a ref return property. Moving  
from POD members to functions in order to support more complex logic is  
the primary motivation of properties.
February 06, 2009
Re: property syntax problems
Robert Jacques wrote:
> Also, the x.y.z = 10 not doing anything when y is a struct from your 
> other post is a well known issue is all languages that have POD struct 
> (As far as I know). The solution is to move x.y to a ref return 
> property. Moving from POD members to functions in order to support more 
> complex logic is the primary motivation of properties.

This has given me some trouble in C#. As a result, anything complicated 
in my company's product (anything that is difficult to initialize with 
all the proper fields) is a class, and anything remaining that is a 
struct has only read-only properties.
Top | Discussion index | About this forum | D home