www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Properties don't behave like variables?

reply "Mehrdad" <wfunction hotmail.com> writes:
Why doesn't this compile?

 property int foo() { return 1; }
 property void foo(int v) { }

void main()
{
	foo |= 2;
}
May 06 2012
next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Monday, May 07, 2012 04:05:20 Mehrdad wrote:
 Why doesn't this compile?
 
  property int foo() { return 1; }
  property void foo(int v) { }
 
 void main()
 {
 	foo |= 2;
 }

Because unfortunately, properties aren't currently set up to be quite as advanced as that. Properties read like variables and write like variables, but they don't read and write at the same time like variables do. foo = foo | 2; would work, because each property usage is translated into a single call to a function, but foo |= 2; doesn't, because it would require it be translated into foo = foo | 2; and then translated into calls to the property functions. I'd definitiely argue that it should work that way, but D's properties are simplistic enough that they don't currently. There may or may not be an enhancement request for it, but if not, then there probably should be. Another example which is brought up from time to time is ++foo; It doesn't work either, and for the same reasons. - Jonathan M Davis
May 06 2012
prev sibling next sibling parent "Era Scarecrow" <rtcvb32 yahoo.com> writes:
On Monday, 7 May 2012 at 02:05:21 UTC, Mehrdad wrote:
 Why doesn't this compile?

  property int foo() { return 1; }
  property void foo(int v) { }

 void main()
 {
 	foo |= 2;
 }

Off hand I would say because it doesn't go to anything (Open the box... What do you mean what box? That invisible one over there can't you see it!?)... Might be better to ask in D.learn, I try and refrain topics unless it actually is in more depth or requires advanced answers. Consider... property int sq(int x) { return x * x;} void main(){ int x = 5; writeln(x.sq); //should print 25 }
May 06 2012
prev sibling next sibling parent "Mehrdad" <wfunction hotmail.com> writes:
 Era Scarecrow: I don't understand your response.


 Jon: Should I submit an enhancement?
May 06 2012
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Monday, May 07, 2012 04:52:32 Mehrdad wrote:
  Jon: Should I submit an enhancement?

If you can't find an existing one. I haven't found one. - Jonathan M Davis
May 06 2012
prev sibling next sibling parent "Mehrdad" <wfunction hotmail.com> writes:
On Monday, 7 May 2012 at 03:06:12 UTC, Jonathan M Davis wrote:
 On Monday, May 07, 2012 04:52:32 Mehrdad wrote:
  Jon: Should I submit an enhancement?

If you can't find an existing one. I haven't found one. - Jonathan M Davis

Ok thanks. http://d.puremagic.com/issues/show_bug.cgi?id=8056
May 06 2012
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 5/7/12, Mehrdad <wfunction hotmail.com> wrote:
 Why doesn't this compile?

Upboat: http://d.puremagic.com/issues/show_bug.cgi?id=8006 Maybe the title could use some work though.
May 07 2012
prev sibling next sibling parent Gor Gyolchanyan <gor.f.gyolchanyan gmail.com> writes:
I think the properties could be much more useful as a library solution.
I'm thinking a template, which generates a structure with all
necessary operators overloaded.
It would be much more flexible. The only downside would be absence of
syntax sugar.
It would work faster too in cases of opOpAssign, because opOpAssign is
generally faster then a combination of opAssign and opBinary.

On Mon, May 7, 2012 at 6:19 AM, Jonathan M Davis <jmdavisProg gmx.com> wrot=
e:
 On Monday, May 07, 2012 04:05:20 Mehrdad wrote:
 Why doesn't this compile?

  property int foo() { return 1; }
  property void foo(int v) { }

 void main()
 {
 =C2=A0 =C2=A0 =C2=A0 foo |=3D 2;
 }

Because unfortunately, properties aren't currently set up to be quite as advanced as that. Properties read like variables and write like variables=

 they don't read and write at the same time like variables do.

 foo =3D foo | 2;

 would work, because each property usage is translated into a single call =

 function, but

 foo |=3D 2;

 doesn't, because it would require it be translated into

 foo =3D foo | 2;

 and then translated into calls to the property functions. I'd definitiely=

 that it should work that way, but D's properties are simplistic enough th=

 they don't currently. There may or may not be an enhancement request for =

 but if not, then there probably should be.

 Another example which is brought up from time to time is

 ++foo;

 It doesn't work either, and for the same reasons.

 - Jonathan M Davis

--=20 Bye, Gor Gyolchanyan.
May 07 2012
prev sibling next sibling parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Sun, 06 May 2012 22:05:20 -0400, Mehrdad <wfunction hotmail.com> wrote:

 Why doesn't this compile?

  property int foo() { return 1; }
  property void foo(int v) { }

 void main()
 {
 	foo |= 2;
 }

It's like this in C#. I can't decide whether I like it better in D or C#. Clearly the compiler lowering of foo |= 2 to foo = foo | 2 would be benficial in terms of less code to write. But I also like having control over how properties can implement operators. For example, the above is two function calls, but it may be easier/more efficient written as one. The issue is, how do you do that? The current definition syntax doesn't lend itself well to extension... -Steve
May 07 2012
next sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2012-05-07 14:43, Steven Schveighoffer wrote:

 It's like this in C#.

 I can't decide whether I like it better in D or C#. Clearly the compiler
 lowering of foo |= 2 to foo = foo | 2 would be benficial in terms of
 less code to write.

 But I also like having control over how properties can implement
 operators. For example, the above is two function calls, but it may be
 easier/more efficient written as one. The issue is, how do you do that?

 The current definition syntax doesn't lend itself well to extension...

 -Steve

If an operator is overloaded use that single function, otherwise do a rewirte. -- /Jacob Carlborg
May 07 2012
parent Jacob Carlborg <doob me.com> writes:
On 2012-05-07 21:53, Steven Schveighoffer wrote:

 How do you overload the operator for a property? For example:

Hm, I didn't think that one through :) -- /Jacob Carlborg
May 07 2012
prev sibling next sibling parent Artur Skawina <art.08.09 gmail.com> writes:
 On 2012-05-07 21:53, Steven Schveighoffer wrote:
 
 How do you overload the operator for a property? For example:


It can of course be done [1], but i think the question was whether the compiler should do the obvious rewrite from 'prop() |= 2' to 'prop(prop()|2)'. Unconditionally, as not doing it every time would be confusing and lead to bugs where the setter gets bypassed. But what about the case where you want to return a ref to /different/ objects? I guess mandating a setter wouldn't be problem, and still better than the alternative. artur [1] I shouldn't even be posting this, as someone might actually think about using something like it... struct S { int i; property ref p() { return *cast(PropProxy!(typeof(this),"i")*)&this; } } int main() { S s; s.p |= 2; return s.p; } struct PropProxy(RT, string sym) { property ref data() { return *cast(RT*)&this; } property ref get() { return __traits(getMember, data, sym); } alias get this; auto opOpAssign(string op, T)(T b) { return mixin("data." ~ sym ~ " " ~ op ~ "= b"); } } Keep in mind this isn't a serious suggestion, more of a joke; i wrote it just out of curiosity, to check if GDC would be able to turn it all into "mov $0x2, %eax; ret;". ;)
May 07 2012
prev sibling parent Artur Skawina <art.08.09 gmail.com> writes:
On 05/08/12 00:32, Iain Buclaw wrote:
 On 7 May 2012 23:23, Artur Skawina <art.08.09 gmail.com> wrote:
 On 2012-05-07 21:53, Steven Schveighoffer wrote:

 How do you overload the operator for a property? For example:


It can of course be done [1], but i think the question was whether the compiler should do the obvious rewrite from 'prop() |= 2' to 'prop(prop()|2)'. Unconditionally, as not doing it every time would be confusing and lead to bugs where the setter gets bypassed. But what about the case where you want to return a ref to /different/ objects? I guess mandating a setter wouldn't be problem, and still better than the alternative. artur [1] I shouldn't even be posting this, as someone might actually think about using something like it... struct S { int i; property ref p() { return *cast(PropProxy!(typeof(this),"i")*)&this; } } int main() { S s; s.p |= 2; return s.p; } struct PropProxy(RT, string sym) { property ref data() { return *cast(RT*)&this; } property ref get() { return __traits(getMember, data, sym); } alias get this; auto opOpAssign(string op, T)(T b) { return mixin("data." ~ sym ~ " " ~ op ~ "= b"); } } Keep in mind this isn't a serious suggestion, more of a joke; i wrote it just out of curiosity, to check if GDC would be able to turn it all into "mov $0x2, %eax; ret;". ;)

Your wishful thinking serves you well. :-)

Just to make it clear - the above results in: 08049e50 <_Dmain>: 8049e50: 55 push %ebp 8049e51: b8 02 00 00 00 mov $0x2,%eax 8049e56: 89 e5 mov %esp,%ebp 8049e58: 5d pop %ebp 8049e59: c3 ret and i believe that after Iain's recent GDC ABI changes the frame pointer manipulation is gone, so it all *really* compiles down to just one instruction. But i haven't checked with a current GDC. r748:ab99d67f04c2 generates the above asm sequence, which is good enough for this quick test, ;) artur
May 07 2012
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Mon, 07 May 2012 15:35:35 -0400, Jacob Carlborg <doob me.com> wrote:

 On 2012-05-07 14:43, Steven Schveighoffer wrote:

 It's like this in C#.

 I can't decide whether I like it better in D or C#. Clearly the compiler
 lowering of foo |= 2 to foo = foo | 2 would be benficial in terms of
 less code to write.

 But I also like having control over how properties can implement
 operators. For example, the above is two function calls, but it may be
 easier/more efficient written as one. The issue is, how do you do that?

 The current definition syntax doesn't lend itself well to extension...

 -Steve

If an operator is overloaded use that single function, otherwise do a rewirte.

How do you overload the operator for a property? For example: struct S { int x; } struct T { private int _x; property S s() { return S(_x);} property void s(S news) { _x = newS.x; } } How do I define T.s |= 5 ??? I realize we could define opBinary("|") on S, and depend on the rewrite, but I'd rather do it in one operation. -Steve
May 07 2012
prev sibling next sibling parent "Mehrdad" <wfunction hotmail.com> writes:
On Monday, 7 May 2012 at 12:43:42 UTC, Steven Schveighoffer wrote:
 On Sun, 06 May 2012 22:05:20 -0400, Mehrdad 
 <wfunction hotmail.com> wrote:

 Why doesn't this compile?

  property int foo() { return 1; }
  property void foo(int v) { }

 void main()
 {
 	foo |= 2;
 }

It's like this in C#.

Um, I to differ... This compiles just fine in C#: class Program { static int Prop { get { return 0; } set { } } static void Main() { Prop |= 1; } }
May 07 2012
prev sibling next sibling parent reply "Michael" <pr m1xa.com> writes:
On Monday, 7 May 2012 at 02:05:21 UTC, Mehrdad wrote:
 Why doesn't this compile?

  property int foo() { return 1; }
  property void foo(int v) { }

 void main()
 {
 	foo |= 2;
 }

import std.stdio; int pro = 1; property ref auto prop() { return pro; } property void prop(int value) { pro = value; } void main() { writeln(prop |= 2); } No? // dmd 2.059
May 07 2012
parent reply Jacob Carlborg <doob me.com> writes:
On 2012-05-07 22:16, Michael wrote:
 import std.stdio;

 int pro = 1;

  property ref auto prop()
 {
        return pro;
 }

  property void prop(int value)
 {
        pro = value;
 }

 void main()
 {
        writeln(prop |= 2);
 }

You're bypassing the getter. -- /Jacob Carlborg
May 07 2012
parent Jacob Carlborg <doob me.com> writes:
On 2012-05-07 23:34, Jonathan M Davis wrote:

 You mean the setter?

Yes.
 Having a getter property function return by ref does allow you to use a
 property exactly as you would a variable, because you're operating on the ref
 that's returned. It also makes the property function nigh-on-useless, because
 then you're operating on its associated variable outside of the property
 function, making it so that you can no longer control access to it. You pretty
 much might as well make it a public variable at that point. Not to mention,
 even if returning by ref didn't have that problem, it would only work in cases
 where the property function was associated with an actual variable (since you
 have to return a ref to _something_), so it would still be impossible to
 emulate a variable with property functions which calculate the value from
 other variables or which grab the value from somewhere else (e.g. a database).

 - Jonathan M Davis

Exactly. -- /Jacob Carlborg
May 07 2012
prev sibling next sibling parent "Mehrdad" <wfunction hotmail.com> writes:
On Monday, 7 May 2012 at 20:16:27 UTC, Michael wrote:
 No?

No. Remove " property void prop(int value)" and see what happens.
May 07 2012
prev sibling next sibling parent "Chris Cain" <clcain uncg.edu> writes:
Definitely a lot more code, but maybe something like this would
work for this problem:
https://gist.github.com/c65e2cc6011d7887efcd
May 07 2012
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Mon, 07 May 2012 16:15:54 -0400, Mehrdad <wfunction hotmail.com> wrote:

 On Monday, 7 May 2012 at 12:43:42 UTC, Steven Schveighoffer wrote:
 On Sun, 06 May 2012 22:05:20 -0400, Mehrdad <wfunction hotmail.com>  
 wrote:

 Why doesn't this compile?

  property int foo() { return 1; }
  property void foo(int v) { }

 void main()
 {
 	foo |= 2;
 }

It's like this in C#.

Um, I to differ...

Oh! I didn't express myself properly :) It's like this in C# means that the above *does* compile in C# :) Sorry for the confusion. -Steve
May 07 2012
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Monday, May 07, 2012 23:14:36 Jacob Carlborg wrote:
 On 2012-05-07 22:16, Michael wrote:
 import std.stdio;
 
 int pro = 1;
 
  property ref auto prop()
 {
 
        return pro;
 
 }
 
  property void prop(int value)
 {
 
        pro = value;
 
 }
 
 void main()
 {
 
        writeln(prop |= 2);
 
 }

You're bypassing the getter.

You mean the setter? Having a getter property function return by ref does allow you to use a property exactly as you would a variable, because you're operating on the ref that's returned. It also makes the property function nigh-on-useless, because then you're operating on its associated variable outside of the property function, making it so that you can no longer control access to it. You pretty much might as well make it a public variable at that point. Not to mention, even if returning by ref didn't have that problem, it would only work in cases where the property function was associated with an actual variable (since you have to return a ref to _something_), so it would still be impossible to emulate a variable with property functions which calculate the value from other variables or which grab the value from somewhere else (e.g. a database). - Jonathan M Davis
May 07 2012
prev sibling next sibling parent "Chris Cain" <clcain uncg.edu> writes:
On Monday, 7 May 2012 at 21:34:29 UTC, Jonathan M Davis wrote:
 You mean the setter?

 Having a getter property function return by ref does allow you 
 to use a
 property exactly as you would a variable, because you're 
 operating on the ref
 that's returned. It also makes the property function 
 nigh-on-useless, because
 then you're operating on its associated variable outside of the 
 property
 function, making it so that you can no longer control access to 
 it. You pretty
 much might as well make it a public variable at that point. Not 
 to mention,
 even if returning by ref didn't have that problem, it would 
 only work in cases
 where the property function was associated with an actual 
 variable (since you
 have to return a ref to _something_), so it would still be 
 impossible to
 emulate a variable with property functions which calculate the 
 value from
 other variables or which grab the value from somewhere else 
 (e.g. a database).

 - Jonathan M Davis

And what about my idea of returning a struct by ref and using a struct to represent all of the operations you're interested in? As far as I can see, it should work, but admittedly, it's not as slick as it could be.
May 07 2012
prev sibling next sibling parent Iain Buclaw <ibuclaw ubuntu.com> writes:
On 7 May 2012 23:23, Artur Skawina <art.08.09 gmail.com> wrote:
 On 2012-05-07 21:53, Steven Schveighoffer wrote:

 How do you overload the operator for a property? For example:


It can of course be done [1], but i think the question was whether the compiler should do the obvious rewrite from 'prop() |=3D 2' to 'prop(prop=

 Unconditionally, as not doing it every time would be confusing and lead
 to bugs where the setter gets bypassed.
 But what about the case where you want to return a ref to /different/
 objects? I guess mandating a setter wouldn't be problem, and still better
 than the alternative.

 artur

 [1] I shouldn't even be posting this, as someone might actually think abo=

 using something like it...

 =A0 struct S {
 =A0 =A0 =A0int i;
 =A0 =A0 =A0 property ref p() { return *cast(PropProxy!(typeof(this),"i")*=

 =A0 }

 =A0 int main()
 =A0 {
 =A0 =A0 =A0S s;
 =A0 =A0 =A0s.p |=3D 2;
 =A0 =A0 =A0return s.p;
 =A0 }

 =A0 struct PropProxy(RT, string sym) {
 =A0 =A0 =A0 property ref data() { return *cast(RT*)&this; }
 =A0 =A0 =A0 property ref get() { return __traits(getMember, data, sym); }
 =A0 =A0 =A0alias get this;
 =A0 =A0 =A0auto opOpAssign(string op, T)(T b) {
 =A0 =A0 =A0 =A0 return mixin("data." ~ sym ~ " " ~ op ~ "=3D b");
 =A0 =A0 =A0}
 =A0 }

 Keep in mind this isn't a serious suggestion, more of a joke; i wrote it =

 out of curiosity, to check if GDC would be able to turn it all into
 "mov $0x2, %eax; ret;". ;)

Your wishful thinking serves you well. :-) --=20 Iain Buclaw *(p < e ? p++ : p) =3D (c & 0x0f) + '0';
May 07 2012
prev sibling next sibling parent Iain Buclaw <ibuclaw ubuntu.com> writes:
On 7 May 2012 23:43, Artur Skawina <art.08.09 gmail.com> wrote:
 On 05/08/12 00:32, Iain Buclaw wrote:
 On 7 May 2012 23:23, Artur Skawina <art.08.09 gmail.com> wrote:
 On 2012-05-07 21:53, Steven Schveighoffer wrote:

 How do you overload the operator for a property? For example:


It can of course be done [1], but i think the question was whether the compiler should do the obvious rewrite from 'prop() |=3D 2' to 'prop(pr=



 Unconditionally, as not doing it every time would be confusing and lead
 to bugs where the setter gets bypassed.
 But what about the case where you want to return a ref to /different/
 objects? I guess mandating a setter wouldn't be problem, and still bett=



 than the alternative.

 artur

 [1] I shouldn't even be posting this, as someone might actually think a=



 using something like it...

 =A0 struct S {
 =A0 =A0 =A0int i;
 =A0 =A0 =A0 property ref p() { return *cast(PropProxy!(typeof(this),"i"=



 =A0 }

 =A0 int main()
 =A0 {
 =A0 =A0 =A0S s;
 =A0 =A0 =A0s.p |=3D 2;
 =A0 =A0 =A0return s.p;
 =A0 }

 =A0 struct PropProxy(RT, string sym) {
 =A0 =A0 =A0 property ref data() { return *cast(RT*)&this; }
 =A0 =A0 =A0 property ref get() { return __traits(getMember, data, sym);=



 =A0 =A0 =A0alias get this;
 =A0 =A0 =A0auto opOpAssign(string op, T)(T b) {
 =A0 =A0 =A0 =A0 return mixin("data." ~ sym ~ " " ~ op ~ "=3D b");
 =A0 =A0 =A0}
 =A0 }

 Keep in mind this isn't a serious suggestion, more of a joke; i wrote i=



 out of curiosity, to check if GDC would be able to turn it all into
 "mov $0x2, %eax; ret;". ;)

Your wishful thinking serves you well. :-)

Just to make it clear - the above results in: 08049e50 <_Dmain>: =A08049e50: =A0 =A0 =A0 55 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0pus=

 =A08049e51: =A0 =A0 =A0 b8 02 00 00 00 =A0 =A0 =A0 =A0 =A0mov =A0 =A0$0x2=

 =A08049e56: =A0 =A0 =A0 89 e5 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 mov =A0=

 =A08049e58: =A0 =A0 =A0 5d =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0pop=

 =A08049e59: =A0 =A0 =A0 c3 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0ret

 and i believe that after Iain's recent GDC ABI changes the frame pointer
 manipulation is gone, so it all *really* compiles down to just one instru=

Frame pointer manipulation only now occurs on x86 for functions that compile in inline assembler (but not GCC inline assembler, and not naked functions). --=20 Iain Buclaw *(p < e ? p++ : p) =3D (c & 0x0f) + '0';
May 07 2012
prev sibling next sibling parent reply "Michael" <pr m1xa.com> writes:
I see.
So where to vote for this enhancement?
May 14 2012
parent Michael <pr m1xa.com> writes:
Any news?
Jul 21 2012
prev sibling next sibling parent "Mehrdad" <wfunction hotmail.com> writes:
On Monday, 14 May 2012 at 21:08:15 UTC, Michael wrote:
 I see.
 So where to vote for this enhancement?

http://forum.dlang.org/thread/xcbweciovapinaicxgbn forum.dlang.org?page=1#post-xcbweciovapinaicxgbn:40forum.dlang.org
May 14 2012
prev sibling next sibling parent "Mehrdad" <wfunction hotmail.com> writes:
On Monday, 14 May 2012 at 21:08:15 UTC, Michael wrote:
 I see.
 So where to vote for this enhancement?

Ugh, wrong link... should've been: http://d.puremagic.com/issues/show_bug.cgi?id=8056
May 14 2012
prev sibling parent "Michael" <pr m1xa.com> writes:
On Monday, 14 May 2012 at 21:29:52 UTC, Mehrdad wrote:
 On Monday, 14 May 2012 at 21:08:15 UTC, Michael wrote:
 I see.
 So where to vote for this enhancement?

Ugh, wrong link... should've been: http://d.puremagic.com/issues/show_bug.cgi?id=8056

Done.
May 15 2012