digitalmars.D - Properties don't behave like variables?
- Mehrdad (7/7) May 06 2012 Why doesn't this compile?
- Jonathan M Davis (18/27) May 06 2012 Because unfortunately, properties aren't currently set up to be quite as...
- Era Scarecrow (12/19) May 06 2012 Off hand I would say because it doesn't go to anything (Open the
- Mehrdad (2/2) May 06 2012 @Era Scarecrow: I don't understand your response.
- Jonathan M Davis (3/4) May 06 2012 If you can't find an existing one. I haven't found one.
- Mehrdad (3/7) May 06 2012 Ok thanks.
- Andrej Mitrovic (3/4) May 07 2012 Upboat: http://d.puremagic.com/issues/show_bug.cgi?id=8006
- Gor Gyolchanyan (17/44) May 07 2012 I think the properties could be much more useful as a library solution.
- Steven Schveighoffer (10/17) May 07 2012 It's like this in C#.
- Jacob Carlborg (5/14) May 07 2012 If an operator is overloaded use that single function, otherwise do a
- Steven Schveighoffer (16/32) May 07 2012 How do you overload the operator for a property? For example:
- Jacob Carlborg (4/5) May 07 2012 Hm, I didn't think that one through :)
- Artur Skawina (31/34) May 07 2012 It can of course be done [1], but i think the question was whether the
- Iain Buclaw (9/43) May 07 2012 ut
- Artur Skawina (13/59) May 07 2012 Just to make it clear - the above results in:
- Iain Buclaw (18/74) May 07 2012 er
- Mehrdad (11/23) May 07 2012 Um, I to differ...
- Steven Schveighoffer (4/20) May 07 2012 Oh! I didn't express myself properly :) It's like this in C# means that...
- Michael (17/24) May 07 2012 import std.stdio;
- Mehrdad (3/4) May 07 2012 No.
- Chris Cain (3/3) May 07 2012 Definitely a lot more code, but maybe something like this would
- Jacob Carlborg (4/18) May 07 2012 You're bypassing the getter.
- Jonathan M Davis (14/41) May 07 2012 You mean the setter?
- Chris Cain (5/29) May 07 2012 And what about my idea of returning a struct by ref and using a
- Jacob Carlborg (5/18) May 07 2012 Exactly.
- Michael (2/2) May 14 2012 I see.
Why doesn't this compile? property int foo() { return 1; } property void foo(int v) { } void main() { foo |= 2; }
May 06 2012
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
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
Era Scarecrow: I don't understand your response. Jon: Should I submit an enhancement?
May 06 2012
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
On Monday, 7 May 2012 at 03:06:12 UTC, Jonathan M Davis wrote:On Monday, May 07, 2012 04:52:32 Mehrdad wrote:Ok thanks. http://d.puremagic.com/issues/show_bug.cgi?id=8056Jon: Should I submit an enhancement?If you can't find an existing one. I haven't found one. - Jonathan M Davis
May 06 2012
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
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:, butWhy 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 =to afunction, 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=arguethat it should work that way, but D's properties are simplistic enough th=atthey 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--=20 Bye, Gor Gyolchanyan.
May 07 2012
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; }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
On 2012-05-07 14:43, Steven Schveighoffer wrote: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... -SteveIf an operator is overloaded use that single function, otherwise do a rewirte. -- /Jacob Carlborg
May 07 2012
On Mon, 07 May 2012 15:35:35 -0400, Jacob Carlborg <doob me.com> wrote:On 2012-05-07 14:43, Steven Schveighoffer wrote: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. -Stevelowering 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... -SteveIf an operator is overloaded use that single function, otherwise do a rewirte.
May 07 2012
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
On 2012-05-07 21:53, Steven Schveighoffer wrote: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;". ;)How do you overload the operator for a property? For example:
May 07 2012
On 7 May 2012 23:23, Artur Skawina <art.08.09 gmail.com> wrote:()|2)'.On 2012-05-07 21:53, Steven Schveighoffer wrote: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=How do you overload the operator for a property? For example: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=utusing something like it... =A0 struct S { =A0 =A0 =A0int i; =A0 =A0 =A0 property ref p() { return *cast(PropProxy!(typeof(this),"i")*=)&this; }=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 =justout 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
On 05/08/12 00:32, Iain Buclaw wrote:On 7 May 2012 23:23, Artur Skawina <art.08.09 gmail.com> wrote: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, ;) arturYour wishful thinking serves you well. :-)On 2012-05-07 21:53, Steven Schveighoffer wrote: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;". ;)How do you overload the operator for a property? For example:
May 07 2012
On 7 May 2012 23:43, Artur Skawina <art.08.09 gmail.com> wrote:On 05/08/12 00:32, Iain Buclaw wrote:op()|2)'.On 7 May 2012 23:23, Artur Skawina <art.08.09 gmail.com> wrote:On 2012-05-07 21:53, Steven Schveighoffer wrote: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=How do you overload the operator for a property? For example:erUnconditionally, 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=boutthan the alternative. artur [1] I shouldn't even be posting this, as someone might actually think a=)*)&this; }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);=t just=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=h =A0 %ebpJust 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=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. :-)=A08049e51: =A0 =A0 =A0 b8 02 00 00 00 =A0 =A0 =A0 =A0 =A0mov =A0 =A0$0x2=,%eax=A08049e56: =A0 =A0 =A0 89 e5 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 mov =A0==A0%esp,%ebp=A08049e58: =A0 =A0 =A0 5d =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0pop==A0 =A0%ebp=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=ction. 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
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:Um, I to differ... class Program { static int Prop { get { return 0; } set { } } static void Main() { Prop |= 1; } }Why doesn't this compile? property int foo() { return 1; } property void foo(int v) { } void main() { foo |= 2; }
May 07 2012
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:-SteveOn Sun, 06 May 2012 22:05:20 -0400, Mehrdad <wfunction hotmail.com> wrote:Um, I to differ...Why doesn't this compile? property int foo() { return 1; } property void foo(int v) { } void main() { foo |= 2; }
May 07 2012
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
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
Definitely a lot more code, but maybe something like this would work for this problem: https://gist.github.com/c65e2cc6011d7887efcd
May 07 2012
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
On Monday, May 07, 2012 23:14:36 Jacob Carlborg wrote:On 2012-05-07 22:16, Michael 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 Davisimport 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.
May 07 2012
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 DavisAnd 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
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 DavisExactly. -- /Jacob Carlborg
May 07 2012
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
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
On Monday, 14 May 2012 at 21:29:52 UTC, Mehrdad wrote:On Monday, 14 May 2012 at 21:08:15 UTC, Michael wrote:Done.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 15 2012