www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Re: property syntax problems

reply Alex Burton <alexibu mac.com> writes:
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
Feb 05 2009
parent reply "Robert Jacques" <sandford jhu.edu> writes:
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  

 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  

 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  

 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.
Feb 05 2009
parent Christopher Wright <dhasenan gmail.com> writes:
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.
Feb 06 2009