www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - getters and setters not an lvalue

reply maarten van damme <maartenvd1994 gmail.com> writes:
In my current code I'd like to do something ala:

void main(){
		getsettest test=new getsettest();
		
		test.value+=1;
}

class getsettest{
	int myvalue;
	
	this(){
	}
	
	 property{
	
		int value(){
			return myvalue;
		}
		
		void value(int value){
			myvalue=value;
		}
	}
}

but this gives the following error:
test.d(4): Error: test.value() is not an lvalue

Is there a rationale behind this decision of not translating
test.value+=1 to test.value= test.value +1 ?
Oct 31 2012
next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
maarten van damme:

 Is there a rationale behind this decision of not translating
 test.value+=1 to test.value= test.value +1 ?

I think it's a temporary limit, meant to be removed/fixed. Bye, bearophile
Oct 31 2012
prev sibling next sibling parent maarten van damme <maartenvd1994 gmail.com> writes:
Ok, looking forward to the fix :)

Btw, I have a foreach loop and in that foreach loop I want to decide
if the current element can stay and if not, I want to remove it. If
removing it yields an empty range in the foreach loop, it crashes.
What's the sane way to do this?
Oct 31 2012
prev sibling next sibling parent "Regan Heath" <regan netmail.co.nz> writes:
On Wed, 31 Oct 2012 14:08:18 -0000, maarten van damme  
<maartenvd1994 gmail.com> wrote:

 Ok, looking forward to the fix :)

 Btw, I have a foreach loop and in that foreach loop I want to decide
 if the current element can stay and if not, I want to remove it. If
 removing it yields an empty range in the foreach loop, it crashes.
 What's the sane way to do this?

Altering the thing you're "foreach"ing over is generally frowned upon because it causes issues like this. Ideally D would const-ify the thing you're foreaching inside the body of the foreach to prevent it. Usually you end up using "for" and an index value instead. R -- Using Opera's revolutionary email client: http://www.opera.com/mail/
Oct 31 2012
prev sibling next sibling parent Jacob Carlborg <doob me.com> writes:
On 2012-10-31 13:46, maarten van damme wrote:
 In my current code I'd like to do something ala:

 void main(){
 		getsettest test=new getsettest();
 		
 		test.value+=1;
 }

 class getsettest{
 	int myvalue;
 	
 	this(){
 	}
 	
 	 property{
 	
 		int value(){
 			return myvalue;
 		}
 		
 		void value(int value){
 			myvalue=value;
 		}
 	}
 }

 but this gives the following error:
 test.d(4): Error: test.value() is not an lvalue

 Is there a rationale behind this decision of not translating
 test.value+=1 to test.value= test.value +1 ?

I think we need implement property rewrite to properly handle this. -- /Jacob Carlborg
Oct 31 2012
prev sibling next sibling parent "Maxim Fomin" <maxim maxim-fomin.ru> writes:
On Wednesday, 31 October 2012 at 12:46:12 UTC, maarten van damme
wrote:
 In my current code I'd like to do something ala:

 void main(){
 		getsettest test=new getsettest();
 		
 		test.value+=1;
 }

 class getsettest{
 	int myvalue;
 	
 	this(){
 	}
 	
 	 property{
 	
 		int value(){
 			return myvalue;
 		}
 		
 		void value(int value){
 			myvalue=value;
 		}
 	}
 }

 but this gives the following error:
 test.d(4): Error: test.value() is not an lvalue

You can make int value() to return by reference.
Oct 31 2012
prev sibling next sibling parent "Maxim Fomin" <maxim maxim-fomin.ru> writes:
On Wednesday, 31 October 2012 at 12:46:12 UTC, maarten van damme 
wrote:
 Is there a rationale behind this decision of not translating
 test.value+=1 to test.value= test.value +1 ?

Probably there were no such decision at all and you just ran into issue which has never worked. BTW properties are syntax construct which allows to omit braces when calling functions. You actually call value function which doesn't return value by reference.
Oct 31 2012
prev sibling next sibling parent "monarch_dodra" <monarchdodra gmail.com> writes:
On Wednesday, 31 October 2012 at 12:46:12 UTC, maarten van damme 
wrote:
 In my current code I'd like to do something ala:

 void main(){
 		getsettest test=new getsettest();
 		
 		test.value+=1;
 }

 class getsettest{
 	int myvalue;
 	
 	this(){
 	}
 	
 	 property{
 	
 		int value(){
 			return myvalue;
 		}
 		
 		void value(int value){
 			myvalue=value;
 		}
 	}
 }

 but this gives the following error:
 test.d(4): Error: test.value() is not an lvalue

 Is there a rationale behind this decision of not translating
 test.value+=1 to test.value= test.value +1 ?

It's not that simple as "test.value" is not an LValue, so from the compiler's perspective "test.value = test.value + 1" calls two different functions, that may or may not have anything to do with each other. The expansion "++ => +=1 => a = a + 1" works if there is only 1 lvalue the whole chain through. Can the compiler really assume it can do that? And is it a smart move to allow it to make that assumption. What you have there is basically an encapsulated field, that does not leak its address: You can take the filed, you can update it with a new value, but you can't modify it. If you allow "test.value+=1", then where does it end? Is this legal? //---- void foo(int& a) {...} foo(test.value); //---- Would you want the compiler to expand it into: //---- void foo(int& a) {...} //scope for __temp { auto __temp = test.value; foo(temp); test.value = temp; } //---- -------------------- IMO, if you take the time to write both functions, instead of just: //---- property ref int front(){return myvalue;} //---- Then the compiler must assume you did it for a reason, and not mess with your code.
Oct 31 2012
prev sibling next sibling parent maarten van damme <maartenvd1994 gmail.com> writes:
Ok, makes sense now :)

2012/10/31 monarch_dodra <monarchdodra gmail.com>:
 On Wednesday, 31 October 2012 at 12:46:12 UTC, maarten van damme wrote:
 In my current code I'd like to do something ala:

 void main(){
                 getsettest test=new getsettest();

                 test.value+=1;
 }

 class getsettest{
         int myvalue;

         this(){
         }

          property{

                 int value(){
                         return myvalue;
                 }

                 void value(int value){
                         myvalue=value;
                 }
         }
 }

 but this gives the following error:
 test.d(4): Error: test.value() is not an lvalue

 Is there a rationale behind this decision of not translating
 test.value+=1 to test.value= test.value +1 ?

It's not that simple as "test.value" is not an LValue, so from the compiler's perspective "test.value = test.value + 1" calls two different functions, that may or may not have anything to do with each other. The expansion "++ => +=1 => a = a + 1" works if there is only 1 lvalue the whole chain through. Can the compiler really assume it can do that? And is it a smart move to allow it to make that assumption. What you have there is basically an encapsulated field, that does not leak its address: You can take the filed, you can update it with a new value, but you can't modify it. If you allow "test.value+=1", then where does it end? Is this legal? //---- void foo(int& a) {...} foo(test.value); //---- Would you want the compiler to expand it into: //---- void foo(int& a) {...} //scope for __temp { auto __temp = test.value; foo(temp); test.value = temp; } //---- -------------------- IMO, if you take the time to write both functions, instead of just: //---- property ref int front(){return myvalue;} //---- Then the compiler must assume you did it for a reason, and not mess with your code.

Oct 31 2012
prev sibling next sibling parent reply "Michael" <pr m1xa.com> writes:
 but this gives the following error:
 test.d(4): Error: test.value() is not an lvalue

 Is there a rationale behind this decision of not translating
 test.value+=1 to test.value= test.value +1 ?

http://forum.dlang.org/thread/xcbweciovapinaicxgbn forum.dlang.org and http://d.puremagic.com/issues/show_bug.cgi?id=8006
Oct 31 2012
parent Jacob Carlborg <doob me.com> writes:
On 2012-10-31 23:48, Adam D. Ruppe wrote:

 I tried it and found getting almost there is easy... but getting it
 to work in a bunch of edge cases is incredibly difficult.

I can imagine operator overloading, opDispatch and similar features making it a lot harder. -- /Jacob Carlborg
Nov 01 2012
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 10/31/12, Michael <pr m1xa.com> wrote:
 http://d.puremagic.com/issues/show_bug.cgi?id=8006

I wonder if this is low-hanging fruit to implement in the DMD frontend. Could we really just implement "var.property += 5;" to "var.property = var.property + 5;" or is it much more complicated than that.. I might have a go at this soon.
Oct 31 2012
prev sibling next sibling parent "Adam D. Ruppe" <destructionator gmail.com> writes:
On Wednesday, 31 October 2012 at 22:46:17 UTC, Andrej Mitrovic 
wrote:
 I wonder if this is low-hanging fruit to implement in the DMD
 frontend.

I tried it and found getting almost there is easy... but getting it to work in a bunch of edge cases is incredibly difficult.
Oct 31 2012
prev sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 10/31/12, Adam D. Ruppe <destructionator gmail.com> wrote:
 On Wednesday, 31 October 2012 at 22:46:17 UTC, Andrej Mitrovic
 wrote:
 I wonder if this is low-hanging fruit to implement in the DMD
 frontend.

I tried it and found getting almost there is easy... but getting it to work in a bunch of edge cases is incredibly difficult.

Could you share the failing test-cases? The patches would be welcome too! :]
Oct 31 2012