digitalmars.D - Using ()s in property functions
- dsimcha (22/22) Jun 28 2010 Once enforcement of @property is enabled, we need to decide whether call...
- Rainer Deyke (17/36) Jun 28 2010 Allowing parentheses also leads to ambiguity:
- Robert Jacques (5/10) Jun 28 2010 No, Walter doesn't. Walter and others wanted zero and one argument
- Robert Jacques (10/43) Jun 28 2010 So... If we allow properties to be called using () syntax, we have corne...
- Nick Sabalausky (5/56) Jun 28 2010 Hell no. It's far better than what we had before, and far better than ju...
- Robert Jacques (14/28) Jun 28 2010 What baby? @property was introduced solely to clarify the ambiguity of t...
- Nick Sabalausky (11/39) Jun 28 2010 Crazy idea:
- Robert Jacques (12/60) Jun 28 2010 1. You'd get a closure, not a lambda, which generally would require a he...
- Nick Sabalausky (28/53) Jun 29 2010 Then maybe what we need is a way to specify what overload of a function ...
- Steven Schveighoffer (18/64) Jun 29 2010 I don't think a delegate to a property is a common need. Besides, you
- Steven Schveighoffer (15/43) Jun 29 2010 Require it. Otherwise, we are left with the same situation as before. ...
- Chad J (8/21) Jun 29 2010 That's the spirit of it. Properties are fields, except much more
- Chad J (3/26) Jun 29 2010 (1) Grab the pointer. T* ptr = ∝
- Steven Schveighoffer (9/35) Jun 29 2010 Why would this assert fail? If a property returns a ref, then you set
- Leandro Lucarella (12/29) Jun 29 2010 Is not the same at all! prop = val will call the setter function, *ptr
- Steven Schveighoffer (13/35) Jun 29 2010 It returns a ref. That can't be a calculated value. If it's a calculat...
- Andrei Alexandrescu (14/34) Jun 29 2010 It's a "calculated reference", e.g. several instances could share the
- Steven Schveighoffer (9/42) Jun 29 2010 Yes, my point was simply, for anything that returns ref:
- BLS (5/6) Jun 29 2010 should be :
- Robert Jacques (2/8) Jun 29 2010 You're forgetting type inference.
- Robert Jacques (14/48) Jun 29 2010 Okay, but what about non-ref properties? i.e.
- Andrei Alexandrescu (4/63) Jun 29 2010 I don't think you should be able to even take the address of a non-ref
- Jonathan M Davis (30/35) Jun 29 2010 In order to have a properly reference a non-ref property, you would have...
- Robert Jacques (8/69) Jun 29 2010 On Tue, 29 Jun 2010 23:41:48 -0400, Andrei Alexandrescu
- Chad J (14/86) Jun 29 2010 ref parameters are easily handled by property expression rewriting:
- Robert Jacques (5/92) Jun 29 2010 Nope. That's a data race. Consider the case where foo has access to prop...
- Andrei Alexandrescu (3/82) Jun 29 2010 I think that would be very error-prone.
- Andrei Alexandrescu (6/78) Jun 29 2010 Indeed properties with separate get and set that don't expose references...
- Steven Schveighoffer (32/37) Jul 01 2010 properties are not fields, they are restricted fields. That is, you can...
- sclytrack (5/5) Jul 07 2010 C# doesn't allow ref on properties.
- sclytrack (2/7) Jul 07 2010 Sorry about that, it does not appear to work, I should test the code bef...
- Chad J (7/52) Jun 29 2010 Ah, so we're speaking only of ref-returning properties. It took me this
- Chad J (11/39) Jun 29 2010 I don't think it should be possible to take the address of a property.
- Jonathan M Davis (3/31) Jun 29 2010 FWIW, TDPL says that you can't use the parens when using a property func...
Once enforcement of property is enabled, we need to decide whether calling an property function using ()s should be legal. In other words, should property **require** omission of ()s or just allow it? My vote is for just allowing omission, because I've run into the following ambiguity while debugging std.range. Here's a reduced test case: struct Foo { uint num; property ref uint front() { return num; } } void main() { Foo foo; uint* bar = &foo.front; // Tries to return a delegate. } If I can assume that property functions can be called with explicit ()s to forcibly disambiguate this situation, then I can fix these kinds of bugs by simply doing a: uint* bar = &(foo.front()); Can we finalize the idea that this will continue to be allowed now so that I can fix the relevant bugs in Phobos and know that my fix won't be broken in a few compiler releases?
Jun 28 2010
On 6/28/2010 20:40, dsimcha wrote:Once enforcement of property is enabled, we need to decide whether calling an property function using ()s should be legal.No, "we" don't. Walter does.In other words, should property **require** omission of ()s or just allow it? My vote is for just allowing omission, because I've run into the following ambiguity while debugging std.range. Here's a reduced test case: struct Foo { uint num; property ref uint front() { return num; } } void main() { Foo foo; uint* bar = &foo.front; // Tries to return a delegate. }Allowing parentheses also leads to ambiguity: struct Foo { uint num; property int delegate() front() { return delegate (){ return 5; }; } } void main() { Foo foo; auto bar = foo.front(); // What is the type of 'bar'? } The problem is that 'front' refers to two things: the property and its accessor function. So long as this is the case, ambiguity is unavoidable. -- Rainer Deyke - rainerd eldwood.com
Jun 28 2010
On Tue, 29 Jun 2010 00:02:32 -0400, Rainer Deyke <rainerd eldwood.com> wrote:On 6/28/2010 20:40, dsimcha wrote:No, Walter doesn't. Walter and others wanted zero and one argument functions to be allowed to behave like properties which is entirely different from properties behaving like functions.Once enforcement of property is enabled, we need to decide whether calling an property function using ()s should be legal.No, "we" don't. Walter does.
Jun 28 2010
On Tue, 29 Jun 2010 00:02:32 -0400, Rainer Deyke <rainerd eldwood.com> wrote:On 6/28/2010 20:40, dsimcha wrote:So... If we allow properties to be called using () syntax, we have corner case ambiguities. And if we don't allow properties to be called using () syntax, we have corner case ambiguities and a minor loss of function (because one ambiguity can't be expressed). Add in Andrei's posts about the difficulty in deciding what methods should and shouldn't be properties, and the more it seems that the real world experience with properties is indicating that property is a mis-feature that should be dropped from the language.In other words, should property **require** omission of ()s or just allow it? My vote is for just allowing omission, because I've run into the following ambiguity while debugging std.range. Here's a reduced test case: struct Foo { uint num; property ref uint front() { return num; } } void main() { Foo foo; uint* bar = &foo.front; // Tries to return a delegate. }Allowing parentheses also leads to ambiguity: struct Foo { uint num; property int delegate() front() { return delegate (){ return 5; }; } } void main() { Foo foo; auto bar = foo.front(); // What is the type of 'bar'? } The problem is that 'front' refers to two things: the property and its accessor function. So long as this is the case, ambiguity is unavoidable.
Jun 28 2010
"Robert Jacques" <sandford jhu.edu> wrote in message news:op.ve1p6xrt26stm6 sandford.myhome.westell.com...On Tue, 29 Jun 2010 00:02:32 -0400, Rainer Deyke <rainerd eldwood.com> wrote:Hell no. It's far better than what we had before, and far better than just simply not having properties. I wouldn't mind improvements, but as for ditching it: there's a baby in that bathwater.On 6/28/2010 20:40, dsimcha wrote:So... If we allow properties to be called using () syntax, we have corner case ambiguities. And if we don't allow properties to be called using () syntax, we have corner case ambiguities and a minor loss of function (because one ambiguity can't be expressed). Add in Andrei's posts about the difficulty in deciding what methods should and shouldn't be properties, and the more it seems that the real world experience with properties is indicating that property is a mis-feature that should be dropped from the language.In other words, should property **require** omission of ()s or just allow it? My vote is for just allowing omission, because I've run into the following ambiguity while debugging std.range. Here's a reduced test case: struct Foo { uint num; property ref uint front() { return num; } } void main() { Foo foo; uint* bar = &foo.front; // Tries to return a delegate. }Allowing parentheses also leads to ambiguity: struct Foo { uint num; property int delegate() front() { return delegate (){ return 5; }; } } void main() { Foo foo; auto bar = foo.front(); // What is the type of 'bar'? } The problem is that 'front' refers to two things: the property and its accessor function. So long as this is the case, ambiguity is unavoidable.
Jun 28 2010
On Tue, 29 Jun 2010 01:38:45 -0400, Nick Sabalausky <a a.a> wrote:"Robert Jacques" <sandford jhu.edu> wrote in message[snip]What baby? property was introduced solely to clarify the ambiguity of the corner case of returning a zero-argument delegate from a method. That's it. Methods-as-properties existed long before the property was proposed. (I'm not suggesting in any way that methods-as-properties should be thrown out, because that really would be throwing the baby out with the bath water.) P.S. The other reason for introducing the property was to allow a library writer to force certain coding standards on the library users. Some like this, some hate this. My count had a con from every pro, but not a pro for every con. However, the pro-less cons were mostly mitigated by leaving in methods-as-properties, making the final verdict one of those agree to disagree compromises.So... If we allow properties to be called using () syntax, we have corner case ambiguities. And if we don't allow properties to be called using () syntax, we have corner case ambiguities and a minor loss of function (because one ambiguity can't be expressed). Add in Andrei's posts about the difficulty in deciding what methods should and shouldn't be properties, and the more it seems that the real world experience with properties is indicating that property is a mis-feature that should be dropped from the language.Hell no. It's far better than what we had before, and far better than just simply not having properties. I wouldn't mind improvements, but as for ditching it: there's a baby in that bathwater.
Jun 28 2010
"dsimcha" <dsimcha yahoo.com> wrote in message news:i0bme6$2phb$1 digitalmars.com...Once enforcement of property is enabled, we need to decide whether calling an property function using ()s should be legal. In other words, should property **require** omission of ()s or just allow it? My vote is for just allowing omission, because I've run into the following ambiguity while debugging std.range. Here's a reduced test case: struct Foo { uint num; property ref uint front() { return num; } } void main() { Foo foo; uint* bar = &foo.front; // Tries to return a delegate. } If I can assume that property functions can be called with explicit ()s to forcibly disambiguate this situation, then I can fix these kinds of bugs by simply doing a: uint* bar = &(foo.front()); Can we finalize the idea that this will continue to be allowed now so that I can fix the relevant bugs in Phobos and know that my fix won't be broken in a few compiler releases?Crazy idea: The whole point of properties is to simulate a member that's *not* a function. With that in mind, does it even make sense to allow the use of unary "&" to get a delegate to a property at all? On the off-chance that you really do need a delegate to a setter/getter you can just make a lambda - and that works exactly the same even if it's a real member variable instead of a property. And inlining could take care of any performance issues. Somewhat related question: What normally happens when you try to get a delegate to an overloaded function?
Jun 28 2010
On Tue, 29 Jun 2010 01:53:05 -0400, Nick Sabalausky <a a.a> wrote:"dsimcha" <dsimcha yahoo.com> wrote in message news:i0bme6$2phb$1 digitalmars.com...1. You'd get a closure, not a lambda, which generally would require a heap allocation. 2. The idea's not too crazy, I've been having similar thoughts. However, 3. D's a system's programming language and not being able to get a function pointer to a function seems wrong. 4. There's actually valid use cases where getting the address of a property makes sense. One of the intents of properties is to allow a library to upgrade a variable to a set of methods without breaking third party user code. And in the new version of your library, taking the address might make sense or be needed due to new functionality.Once enforcement of property is enabled, we need to decide whether calling an property function using ()s should be legal. In other words, should property **require** omission of ()s or just allow it? My vote is for just allowing omission, because I've run into the following ambiguity while debugging std.range. Here's a reduced test case: struct Foo { uint num; property ref uint front() { return num; } } void main() { Foo foo; uint* bar = &foo.front; // Tries to return a delegate. } If I can assume that property functions can be called with explicit ()s to forcibly disambiguate this situation, then I can fix these kinds of bugs by simply doing a: uint* bar = &(foo.front()); Can we finalize the idea that this will continue to be allowed now so that I can fix the relevant bugs in Phobos and know that my fix won't be broken in a few compiler releases?Crazy idea: The whole point of properties is to simulate a member that's *not* a function. With that in mind, does it even make sense to allow the use of unary "&" to get a delegate to a property at all? On the off-chance that you really do need a delegate to a setter/getter you can just make a lambda - and that works exactly the same even if it's a real member variable instead of a property. And inlining could take care of any performance issues.Somewhat related question: What normally happens when you try to get a delegate to an overloaded function?It grabs the first overload, IIRC.
Jun 28 2010
"Robert Jacques" <sandford jhu.edu> wrote in message news:op.ve1us1xj26stm6 sandford.myhome.westell.com...On Tue, 29 Jun 2010 01:53:05 -0400, Nick Sabalausky <a a.a> wrote:Then maybe what we need is a way to specify what overload of a function you want to get a reference to. Something along these lines (disregard the exact syntax, I'm looking more at the semantics): main() { auto a = &foo; // Either same behavior as now, or disallowed for overloaded funcs, or a collection of delegates } Then, that would open the door for this: class Foo { property ref uint foo() {/*...*/} } main() { auto f = new Foo(); auto a = &f.foo; // Address of returned value auto b = &f.foo(void); // Delegate to getter //auto c = &f.foo(uint); // If exists, delegate to setter }Crazy idea: The whole point of properties is to simulate a member that's *not* a function. With that in mind, does it even make sense to allow the use of unary "&" to get a delegate to a property at all? On the off-chance that you really do need a delegate to a setter/getter you can just make a lambda - and that works exactly the same even if it's a real member variable instead of a property. And inlining could take care of any performance issues.1. You'd get a closure, not a lambda, which generally would require a heap allocation. 2. The idea's not too crazy, I've been having similar thoughts. However, 3. D's a system's programming language and not being able to get a function pointer to a function seems wrong. 4. There's actually valid use cases where getting the address of a property makes sense. One of the intents of properties is to allow a library to upgrade a variable to a set of methods without breaking third party user code. And in the new version of your library, taking the address might make sense or be needed due to new functionality.Somewhat related question: What normally happens when you try to get a delegate to an overloaded function?It grabs the first overload, IIRC.
Jun 29 2010
On Tue, 29 Jun 2010 01:53:05 -0400, Nick Sabalausky <a a.a> wrote:"dsimcha" <dsimcha yahoo.com> wrote in message news:i0bme6$2phb$1 digitalmars.com...I don't think a delegate to a property is a common need. Besides, you would almost expect something that accesses both read/write properties. I'm sure someone can come up with a way to do this in a type-agnostic way (a "property delegate" if you will...) If one truly needs a delegate to a property, why not use __traits/meta to do it? meta.delegateOf(foo.front); This could actually solve the issue of how to get a specific delegate: struct S { void foo(int x); void foo(string s); } S s; auto d1 = meta.delegateOf(s.foo, int); auto d2 = meta.delegateOf(s.foo, string); -SteveOnce enforcement of property is enabled, we need to decide whether calling an property function using ()s should be legal. In other words, should property **require** omission of ()s or just allow it? My vote is for just allowing omission, because I've run into the following ambiguity while debugging std.range. Here's a reduced test case: struct Foo { uint num; property ref uint front() { return num; } } void main() { Foo foo; uint* bar = &foo.front; // Tries to return a delegate. } If I can assume that property functions can be called with explicit ()s to forcibly disambiguate this situation, then I can fix these kinds of bugs by simply doing a: uint* bar = &(foo.front()); Can we finalize the idea that this will continue to be allowed now so that I can fix the relevant bugs in Phobos and know that my fix won't be broken in a few compiler releases?Crazy idea: The whole point of properties is to simulate a member that's *not* a function. With that in mind, does it even make sense to allow the use of unary "&" to get a delegate to a property at all? On the off-chance that you really do need a delegate to a setter/getter you can just make a lambda - and that works exactly the same even if it's a real member variable instead of a property. And inlining could take care of any performance issues.
Jun 29 2010
On Mon, 28 Jun 2010 22:40:06 -0400, dsimcha <dsimcha yahoo.com> wrote:Once enforcement of property is enabled, we need to decide whether calling an property function using ()s should be legal. In other words, should property **require** omission of ()s or just allow it?Require it. Otherwise, we are left with the same situation as before. We already had optional parentheses for properties, and it was/is an ambiguity disaster. It's the whole reason for introducing property in the first place.My vote is for just allowing omission, because I've run into the following ambiguity while debugging std.range. Here's a reduced test case: struct Foo { uint num; property ref uint front() { return num; } } void main() { Foo foo; uint* bar = &foo.front; // Tries to return a delegate. } If I can assume that property functions can be called with explicit ()s to forcibly disambiguate this situation, then I can fix these kinds of bugs by simply doing a: uint* bar = &(foo.front()); Can we finalize the idea that this will continue to be allowed now so that I can fix the relevant bugs in Phobos and know that my fix won't be broken in a few compiler releases?If I'm reading this correctly, you are saying that you want &foo.front to return a pointer to uint, not a delegate? This is what I'd expect if property forced no parentheses. That is, foo.front can be replaced with (foo.front()) always, so &foo.front always translates to &(foo.front()). What this means is that you can't get a delegate to the property function. This makes sense -- if you replaced the property with an actual field, you wouldn't be able to get a delegate anyways. A property should operate just like a field. -Steve
Jun 29 2010
On 06/29/2010 07:16 AM, Steven Schveighoffer wrote:If I'm reading this correctly, you are saying that you want &foo.front to return a pointer to uint, not a delegate? This is what I'd expect if property forced no parentheses. That is, foo.front can be replaced with (foo.front()) always, so &foo.front always translates to &(foo.front()). What this means is that you can't get a delegate to the property function. This makes sense -- if you replaced the property with an actual field, you wouldn't be able to get a delegate anyways. A property should operate just like a field. -SteveThat's the spirit of it. Properties are fields, except much more powerful but addressing is tricky. There is one thing that bugs me about this solution though. What if the user does this: (1) Grab the pointer. *ptr = prop; (2) assigns to it. *ptr = val; (3) expects the result to be updated in prop. assert(val == prop);
Jun 29 2010
Whoops, made a mistake. On 06/29/2010 08:03 AM, Chad J wrote:On 06/29/2010 07:16 AM, Steven Schveighoffer wrote:(1) Grab the pointer. T* ptr = ∝If I'm reading this correctly, you are saying that you want &foo.front to return a pointer to uint, not a delegate? This is what I'd expect if property forced no parentheses. That is, foo.front can be replaced with (foo.front()) always, so &foo.front always translates to &(foo.front()). What this means is that you can't get a delegate to the property function. This makes sense -- if you replaced the property with an actual field, you wouldn't be able to get a delegate anyways. A property should operate just like a field. -SteveThat's the spirit of it. Properties are fields, except much more powerful but addressing is tricky. There is one thing that bugs me about this solution though. What if the user does this: (1) Grab the pointer. *ptr = prop;(2) assigns to it. *ptr = val; (3) expects the result to be updated in prop. assert(val == prop);
Jun 29 2010
On Tue, 29 Jun 2010 08:05:04 -0400, Chad J <chadjoan __spam.is.bad__gmail.com> wrote:Whoops, made a mistake. On 06/29/2010 08:03 AM, Chad J wrote:Why would this assert fail? If a property returns a ref, then you set through that ref. What you did is no different, you just delayed the assignment for a bit. You can reduce your test case to: (1) assign to the property. prop = val; (2) expects the result to be updated in prop. assert(val == prop); -SteveOn 06/29/2010 07:16 AM, Steven Schveighoffer wrote:(1) Grab the pointer. T* ptr = ∝If I'm reading this correctly, you are saying that you want &foo.front to return a pointer to uint, not a delegate? This is what I'd expect if property forced no parentheses. That is, foo.front can be replaced with (foo.front()) always, so &foo.front always translates to &(foo.front()). What this means is that you can't get a delegate to the property function. This makes sense -- if you replaced the property with an actual field, you wouldn't be able to get a delegate anyways. A property should operate just like a field. -SteveThat's the spirit of it. Properties are fields, except much more powerful but addressing is tricky. There is one thing that bugs me about this solution though. What if the user does this: (1) Grab the pointer. *ptr = prop;(2) assigns to it. *ptr = val; (3) expects the result to be updated in prop. assert(val == prop);
Jun 29 2010
Steven Schveighoffer, el 29 de junio a las 08:13 me escribiste:What if it doesn't? If returns a temporary calculated value?Why would this assert fail? If a property returns a refThere is one thing that bugs me about this solution though. What if the user does this: (1) Grab the pointer. *ptr = prop;(1) Grab the pointer. T* ptr = ∝(2) assigns to it. *ptr = val; (3) expects the result to be updated in prop. assert(val == prop);then you set through that ref. What you did is no different, you just delayed the assignment for a bit. You can reduce your test case to: (1) assign to the property. prop = val;Is not the same at all! prop = val will call the setter function, *ptr = val will not! -- Leandro Lucarella (AKA luca) http://llucax.com.ar/ ---------------------------------------------------------------------- GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145 104C 949E BFB6 5F5A 8D05) ---------------------------------------------------------------------- ¿Qué será lo que hace que una brújula siempre marque el norte? - Ser aguja, nada más, y cumplir su misión. -- Ricardo Vaporeso
Jun 29 2010
On Tue, 29 Jun 2010 10:15:10 -0400, Leandro Lucarella <luca llucax.com.ar> wrote:Steven Schveighoffer, el 29 de junio a las 08:13 me escribiste:It returns a ref. That can't be a calculated value. If it's a calculated value then T* ptr = &prop will fail to compile.What if it doesn't? If returns a temporary calculated value?theThere is one thing that bugs me about this solution though. What ifWhy would this assert fail? If a property returns a refuser does this: (1) Grab the pointer. *ptr = prop;(1) Grab the pointer. T* ptr = ∝(2) assigns to it. *ptr = val; (3) expects the result to be updated in prop. assert(val == prop);Maybe you are thinking of something different, here is the code we're discussing: struct Foo { uint num; property ref uint front() { return num; } } -Stevethen you set through that ref. What you did is no different, you just delayed the assignment for a bit. You can reduce your test case to: (1) assign to the property. prop = val;Is not the same at all! prop = val will call the setter function, *ptr = val will not!
Jun 29 2010
Steven Schveighoffer wrote:On Tue, 29 Jun 2010 10:15:10 -0400, Leandro Lucarella <luca llucax.com.ar> wrote:It's a "calculated reference", e.g. several instances could share the same value etc. Once the reference is out, clearly there's no more control. I agree with the view that a property returning ref should be virtually indistinguishable from a field. Currently that's not the case, e.g. if you want to assign to such a property you must add parens: struct A { int x; property ref y() { return x; } } unittest { A a; a.y = 5; // fails a.y() = 5; // works } AndreiSteven Schveighoffer, el 29 de junio a las 08:13 me escribiste:It returns a ref. That can't be a calculated value. If it's a calculated value then T* ptr = &prop will fail to compile.What if it doesn't? If returns a temporary calculated value?if theThere is one thing that bugs me about this solution though. WhatWhy would this assert fail? If a property returns a refuser does this: (1) Grab the pointer. *ptr = prop;(1) Grab the pointer. T* ptr = ∝(2) assigns to it. *ptr = val; (3) expects the result to be updated in prop. assert(val == prop);
Jun 29 2010
On Tue, 29 Jun 2010 11:44:07 -0400, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:Steven Schveighoffer wrote:Yes, my point was simply, for anything that returns ref: auto ptr = &foo(); *ptr = x; is equivalent to foo() = x;On Tue, 29 Jun 2010 10:15:10 -0400, Leandro Lucarella <luca llucax.com.ar> wrote:It's a "calculated reference", e.g. several instances could share the same value etc. Once the reference is out, clearly there's no more control.Steven Schveighoffer, el 29 de junio a las 08:13 me escribiste:It returns a ref. That can't be a calculated value. If it's a calculated value then T* ptr = &prop will fail to compile.What if it doesn't? If returns a temporary calculated value?if theThere is one thing that bugs me about this solution though. WhatWhy would this assert fail? If a property returns a refuser does this: (1) Grab the pointer. *ptr = prop;(1) Grab the pointer. T* ptr = ∝(2) assigns to it. *ptr = val; (3) expects the result to be updated in prop. assert(val == prop);I agree with the view that a property returning ref should be virtually indistinguishable from a field. Currently that's not the case, e.g. if you want to assign to such a property you must add parens: struct A { int x; property ref y() { return x; } } unittest { A a; a.y = 5; // fails a.y() = 5; // works }http://d.puremagic.com/issues/show_bug.cgi?id=3511 -Steve
Jun 29 2010
On 29/06/2010 17:44, Andrei Alexandrescu wrote:struct A { int x; property ref y() { return x; } }should be : struct A { int x; property ref int y() { return x; } } or am I wrong ? bjoern
Jun 29 2010
On Tue, 29 Jun 2010 12:03:38 -0400, BLS <windevguy hotmail.de> wrote:On 29/06/2010 17:44, Andrei Alexandrescu wrote:You're forgetting type inference.struct A { int x; property ref y() { return x; } }should be : struct A { int x; property ref int y() { return x; } } or am I wrong ? bjoern
Jun 29 2010
On Tue, 29 Jun 2010 11:44:07 -0400, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:Steven Schveighoffer wrote:Okay, but what about non-ref properties? i.e. struct A { int x; property int y() { return x; } property int y(int v) { return x = v; } } unittest { A a; int* ptr = &a.x; // works int* ptr = &a.y; // fails } Is there a good way of patching this leak in the property abstraction?On Tue, 29 Jun 2010 10:15:10 -0400, Leandro Lucarella <luca llucax.com.ar> wrote:It's a "calculated reference", e.g. several instances could share the same value etc. Once the reference is out, clearly there's no more control. I agree with the view that a property returning ref should be virtually indistinguishable from a field. Currently that's not the case, e.g. if you want to assign to such a property you must add parens: struct A { int x; property ref y() { return x; } } unittest { A a; a.y = 5; // fails a.y() = 5; // works } AndreiSteven Schveighoffer, el 29 de junio a las 08:13 me escribiste:It returns a ref. That can't be a calculated value. If it's a calculated value then T* ptr = &prop will fail to compile.What if it doesn't? If returns a temporary calculated value?if theThere is one thing that bugs me about this solution though. WhatWhy would this assert fail? If a property returns a refuser does this: (1) Grab the pointer. *ptr = prop;(1) Grab the pointer. T* ptr = ∝(2) assigns to it. *ptr = val; (3) expects the result to be updated in prop. assert(val == prop);
Jun 29 2010
Robert Jacques wrote:On Tue, 29 Jun 2010 11:44:07 -0400, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:I don't think you should be able to even take the address of a non-ref property. AndreiSteven Schveighoffer wrote:Okay, but what about non-ref properties? i.e. struct A { int x; property int y() { return x; } property int y(int v) { return x = v; } } unittest { A a; int* ptr = &a.x; // works int* ptr = &a.y; // fails } Is there a good way of patching this leak in the property abstraction?On Tue, 29 Jun 2010 10:15:10 -0400, Leandro Lucarella <luca llucax.com.ar> wrote:It's a "calculated reference", e.g. several instances could share the same value etc. Once the reference is out, clearly there's no more control. I agree with the view that a property returning ref should be virtually indistinguishable from a field. Currently that's not the case, e.g. if you want to assign to such a property you must add parens: struct A { int x; property ref y() { return x; } } unittest { A a; a.y = 5; // fails a.y() = 5; // works } AndreiSteven Schveighoffer, el 29 de junio a las 08:13 me escribiste:It returns a ref. That can't be a calculated value. If it's a calculated value then T* ptr = &prop will fail to compile.What if it doesn't? If returns a temporary calculated value?if theThere is one thing that bugs me about this solution though. WhatWhy would this assert fail? If a property returns a refuser does this: (1) Grab the pointer. *ptr = prop;(1) Grab the pointer. T* ptr = ∝(2) assigns to it. *ptr = val; (3) expects the result to be updated in prop. assert(val == prop);
Jun 29 2010
On Tuesday 29 June 2010 20:41:48 Andrei Alexandrescu wrote:I don't think you should be able to even take the address of a non-ref property. AndreiIn order to have a properly reference a non-ref property, you would have to have an abstraction which wrapped the object along with its getter and/or setter and treated it exactly like a reference to a public member variable (including dealing with the fact that it could be read-only or write-only). On top of that, that same abstraction would have to be used for references to actual member variables. That way, they could be treated identically be user code, and that code would not have to care whether it was dealing with property functions or a naked member variable. And while I'm sure that such an abstraction is technically feasible, it would likely be an expensive one (particularly for a systems language), and by the time you're talking addresses of things, you're way too low-level to even consider it. Properties are definitely a useful abstraction, but they are by their nature a bit broken - particularly when you get to the low-level stuff - because while they may act like member variables, they _aren't_ member variables. A ref property is giving you essentially what a naked member variable would give you, so it makes some sense to allow you to take its address. However, if it's a non-ref property, I don't think that it really makes sense anymore. What would you take the address of? You'd need one (possibly two) functions and the object that has the property. With a ref, you have the variable itself. It's nowhere near that simple with a non-ref property functions - there may not even _be_ a variable to reference. So, I'd have to agree that it doesn't make sense to take the address of a non-ref property. properties where you can't really treat them quite the same as public member variables, so it's not like it's without precedent. If we really wanted to fix it, we'd need a higher-level reference abstraction than we currently have, it there's a good chance that the abstraction would cost far too much to make sense - particularly for a systems lanuage. - Jonathan M Davis
Jun 29 2010
On Tue, 29 Jun 2010 23:41:48 -0400, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote: .Robert Jacques wrote:I agree with you from a under-the-hood perspective, but I wasn't asking about that. I was asking about the leak in the property abstraction. Not being able to pass non-ref properties to functions by ref is a fairly serious (i.e. common) break/leak in the property abstraction: that properties should be "virtually indistinguishable from a field".On Tue, 29 Jun 2010 11:44:07 -0400, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:I don't think you should be able to even take the address of a non-ref property. AndreiSteven Schveighoffer wrote:Okay, but what about non-ref properties? i.e. struct A { int x; property int y() { return x; } property int y(int v) { return x = v; } } unittest { A a; int* ptr = &a.x; // works int* ptr = &a.y; // fails } Is there a good way of patching this leak in the property abstraction?On Tue, 29 Jun 2010 10:15:10 -0400, Leandro Lucarella <luca llucax.com.ar> wrote:It's a "calculated reference", e.g. several instances could share the same value etc. Once the reference is out, clearly there's no more control. I agree with the view that a property returning ref should be virtually indistinguishable from a field. Currently that's not the case, e.g. if you want to assign to such a property you must add parens: struct A { int x; property ref y() { return x; } } unittest { A a; a.y = 5; // fails a.y() = 5; // works } AndreiSteven Schveighoffer, el 29 de junio a las 08:13 me escribiste:It returns a ref. That can't be a calculated value. If it's a calculated value then T* ptr = &prop will fail to compile.What if it doesn't? If returns a temporary calculated value?if theThere is one thing that bugs me about this solution though. Whatprop);user does this: (1) Grab the pointer. *ptr = prop;(1) Grab the pointer. T* ptr = ∝(2) assigns to it. *ptr = val; (3) expects the result to be updated in prop. assert(val ==Why would this assert fail? If a property returns a ref
Jun 29 2010
On 06/30/2010 12:33 AM, Robert Jacques wrote:On Tue, 29 Jun 2010 23:41:48 -0400, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote: .ref parameters are easily handled by property expression rewriting: void foo( ref bar ) { ... } foo(prop) becomes auto t = prop() foo(t) prop(t) I would handle "out" parameters similarly, but without calling the getter. They are essentially a different way of writing an assignment. Taking the /address/ is a bit different, since there may be no well-defined line of code at which the pointer holding the address dies. The ref parameter, on the other hand, WILL expire when the function returns.Robert Jacques wrote:I agree with you from a under-the-hood perspective, but I wasn't asking about that. I was asking about the leak in the property abstraction. Not being able to pass non-ref properties to functions by ref is a fairly serious (i.e. common) break/leak in the property abstraction: that properties should be "virtually indistinguishable from a field".On Tue, 29 Jun 2010 11:44:07 -0400, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:I don't think you should be able to even take the address of a non-ref property. AndreiSteven Schveighoffer wrote:Okay, but what about non-ref properties? i.e. struct A { int x; property int y() { return x; } property int y(int v) { return x = v; } } unittest { A a; int* ptr = &a.x; // works int* ptr = &a.y; // fails } Is there a good way of patching this leak in the property abstraction?On Tue, 29 Jun 2010 10:15:10 -0400, Leandro Lucarella <luca llucax.com.ar> wrote:It's a "calculated reference", e.g. several instances could share the same value etc. Once the reference is out, clearly there's no more control. I agree with the view that a property returning ref should be virtually indistinguishable from a field. Currently that's not the case, e.g. if you want to assign to such a property you must add parens: struct A { int x; property ref y() { return x; } } unittest { A a; a.y = 5; // fails a.y() = 5; // works } AndreiSteven Schveighoffer, el 29 de junio a las 08:13 me escribiste:It returns a ref. That can't be a calculated value. If it's a calculated value then T* ptr = &prop will fail to compile.What if it doesn't? If returns a temporary calculated value?What if theThere is one thing that bugs me about this solution though.prop);user does this: (1) Grab the pointer. *ptr = prop;(1) Grab the pointer. T* ptr = ∝(2) assigns to it. *ptr = val; (3) expects the result to be updated in prop. assert(val ==Why would this assert fail? If a property returns a ref
Jun 29 2010
On Wed, 30 Jun 2010 01:00:53 -0400, Chad J <chadjoan __spam.is.bad__gmail.com> wrote:On 06/30/2010 12:33 AM, Robert Jacques wrote:Nope. That's a data race. Consider the case where foo has access to prop's object. Essentially, t is stale, so this breaks the concept of reference semantics.On Tue, 29 Jun 2010 23:41:48 -0400, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote: .ref parameters are easily handled by property expression rewriting: void foo( ref bar ) { ... } foo(prop) becomes auto t = prop() foo(t) prop(t) I would handle "out" parameters similarly, but without calling the getter. They are essentially a different way of writing an assignment. Taking the /address/ is a bit different, since there may be no well-defined line of code at which the pointer holding the address dies. The ref parameter, on the other hand, WILL expire when the function returns.Robert Jacques wrote:I agree with you from a under-the-hood perspective, but I wasn't asking about that. I was asking about the leak in the property abstraction. Not being able to pass non-ref properties to functions by ref is a fairly serious (i.e. common) break/leak in the property abstraction: that properties should be "virtually indistinguishable from a field".On Tue, 29 Jun 2010 11:44:07 -0400, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:I don't think you should be able to even take the address of a non-ref property. AndreiSteven Schveighoffer wrote:Okay, but what about non-ref properties? i.e. struct A { int x; property int y() { return x; } property int y(int v) { return x = v; } } unittest { A a; int* ptr = &a.x; // works int* ptr = &a.y; // fails } Is there a good way of patching this leak in the property abstraction?On Tue, 29 Jun 2010 10:15:10 -0400, Leandro Lucarella <luca llucax.com.ar> wrote:It's a "calculated reference", e.g. several instances could share the same value etc. Once the reference is out, clearly there's no more control. I agree with the view that a property returning ref should be virtually indistinguishable from a field. Currently that's not the case, e.g. if you want to assign to such a property you must add parens: struct A { int x; property ref y() { return x; } } unittest { A a; a.y = 5; // fails a.y() = 5; // works } AndreiSteven Schveighoffer, el 29 de junio a las 08:13 me escribiste:It returns a ref. That can't be a calculated value. If it's a calculated value then T* ptr = &prop will fail to compile.What if it doesn't? If returns a temporary calculated value?What if theThere is one thing that bugs me about this solution though.prop);user does this: (1) Grab the pointer. *ptr = prop;(1) Grab the pointer. T* ptr = ∝(2) assigns to it. *ptr = val; (3) expects the result to be updated in prop. assert(val ==Why would this assert fail? If a property returns a ref
Jun 29 2010
Chad J wrote:On 06/30/2010 12:33 AM, Robert Jacques wrote:I think that would be very error-prone. AndreiOn Tue, 29 Jun 2010 23:41:48 -0400, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote: .ref parameters are easily handled by property expression rewriting: void foo( ref bar ) { ... } foo(prop) becomes auto t = prop() foo(t) prop(t)Robert Jacques wrote:I agree with you from a under-the-hood perspective, but I wasn't asking about that. I was asking about the leak in the property abstraction. Not being able to pass non-ref properties to functions by ref is a fairly serious (i.e. common) break/leak in the property abstraction: that properties should be "virtually indistinguishable from a field".On Tue, 29 Jun 2010 11:44:07 -0400, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:I don't think you should be able to even take the address of a non-ref property. AndreiSteven Schveighoffer wrote:Okay, but what about non-ref properties? i.e. struct A { int x; property int y() { return x; } property int y(int v) { return x = v; } } unittest { A a; int* ptr = &a.x; // works int* ptr = &a.y; // fails } Is there a good way of patching this leak in the property abstraction?On Tue, 29 Jun 2010 10:15:10 -0400, Leandro Lucarella <luca llucax.com.ar> wrote:It's a "calculated reference", e.g. several instances could share the same value etc. Once the reference is out, clearly there's no more control. I agree with the view that a property returning ref should be virtually indistinguishable from a field. Currently that's not the case, e.g. if you want to assign to such a property you must add parens: struct A { int x; property ref y() { return x; } } unittest { A a; a.y = 5; // fails a.y() = 5; // works } AndreiSteven Schveighoffer, el 29 de junio a las 08:13 me escribiste:It returns a ref. That can't be a calculated value. If it's a calculated value then T* ptr = &prop will fail to compile.What if it doesn't? If returns a temporary calculated value?What if theThere is one thing that bugs me about this solution though.prop); Why would this assert fail? If a property returns a refuser does this: (1) Grab the pointer. *ptr = prop;(1) Grab the pointer. T* ptr = ∝(2) assigns to it. *ptr = val; (3) expects the result to be updated in prop. assert(val ==
Jun 29 2010
Robert Jacques wrote:On Tue, 29 Jun 2010 23:41:48 -0400, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote: ..Indeed properties with separate get and set that don't expose references are quite different from fields. Those that return ref are more similar to fields. The basic goal is to bring both as close as possible to field syntax and semantics. AndreiRobert Jacques wrote:I agree with you from a under-the-hood perspective, but I wasn't asking about that. I was asking about the leak in the property abstraction. Not being able to pass non-ref properties to functions by ref is a fairly serious (i.e. common) break/leak in the property abstraction: that properties should be "virtually indistinguishable from a field".On Tue, 29 Jun 2010 11:44:07 -0400, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:I don't think you should be able to even take the address of a non-ref property. AndreiSteven Schveighoffer wrote:Okay, but what about non-ref properties? i.e. struct A { int x; property int y() { return x; } property int y(int v) { return x = v; } } unittest { A a; int* ptr = &a.x; // works int* ptr = &a.y; // fails } Is there a good way of patching this leak in the property abstraction?On Tue, 29 Jun 2010 10:15:10 -0400, Leandro Lucarella <luca llucax.com.ar> wrote:It's a "calculated reference", e.g. several instances could share the same value etc. Once the reference is out, clearly there's no more control. I agree with the view that a property returning ref should be virtually indistinguishable from a field. Currently that's not the case, e.g. if you want to assign to such a property you must add parens: struct A { int x; property ref y() { return x; } } unittest { A a; a.y = 5; // fails a.y() = 5; // works } AndreiSteven Schveighoffer, el 29 de junio a las 08:13 me escribiste:It returns a ref. That can't be a calculated value. If it's a calculated value then T* ptr = &prop will fail to compile.What if it doesn't? If returns a temporary calculated value?What if theThere is one thing that bugs me about this solution though.prop);user does this: (1) Grab the pointer. *ptr = prop;(1) Grab the pointer. T* ptr = ∝(2) assigns to it. *ptr = val; (3) expects the result to be updated in prop. assert(val ==Why would this assert fail? If a property returns a ref
Jun 29 2010
On Wed, 30 Jun 2010 00:33:54 -0400, Robert Jacques <sandford jhu.edu> wrote:I agree with you from a under-the-hood perspective, but I wasn't asking about that. I was asking about the leak in the property abstraction. Not being able to pass non-ref properties to functions by ref is a fairly serious (i.e. common) break/leak in the property abstraction: that properties should be "virtually indistinguishable from a field".properties are not fields, they are restricted fields. That is, you can completely control access to a property, but you cannot control access to a field. With a field, you cannot control: - Who has an address to it - What the user sets it to - The action of setting or getting it. Properties allow control over those things. The drawback is you cannot use it exactly like a field. I think we would all agree that the main mode of access to a field is: container.field = x; x = container.field; Properties mimic that functionality perfectly, and that is pretty much it. The one thing I'd like to see for properties is some sort of "property delegate." This could be generated in a struct. What I don't know is how to make it as "virtual" as a real delegate. Another thing I'd like to see (brought up elsewhere in this thread) is some sort of __traits/meta means to get a delegate to a property setter or getter, since with required omission of parens, you can no longer get a delegate to the property. This solution could also be amended to solve another pet peeve of mine: struct S { property void foo(int x); property void foo(string s); } S s; auto d1 = meta.delegateOf(s.foo, int); auto d2 = meta.delegateOf(s.foo, string); -Steve
Jul 01 2010
void doStuff( ref int a) {a++;} doStuff(obj.NumberProperty); //Compiler magic. Stores in local variables behind the scenes. Calls getter and setter.
Jul 07 2010
== Quote from sclytrack (sclytrack fake.com)'s articlevoid doStuff( ref int a) {a++;} doStuff(obj.NumberProperty); //Compiler magic. Stores in local variables behind the scenes. Calls getter and setter.Sorry about that, it does not appear to work, I should test the code before I post.
Jul 07 2010
On 06/29/2010 11:38 AM, Steven Schveighoffer wrote:On Tue, 29 Jun 2010 10:15:10 -0400, Leandro Lucarella <luca llucax.com.ar> wrote:Ah, so we're speaking only of ref-returning properties. It took me this post and some of its replies until I realized this restriction. Sorry, I was speaking about properties in general. Actually this is really cool. I hadn't thought of ref-returns as a way to escape the lack-of-addressability problem. I'm too sleepy to think of the consequences of this, but so far I like it!Steven Schveighoffer, el 29 de junio a las 08:13 me escribiste:It returns a ref. That can't be a calculated value. If it's a calculated value then T* ptr = &prop will fail to compile.What if it doesn't? If returns a temporary calculated value?if theThere is one thing that bugs me about this solution though. WhatWhy would this assert fail? If a property returns a refuser does this: (1) Grab the pointer. *ptr = prop;(1) Grab the pointer. T* ptr = ∝(2) assigns to it. *ptr = val; (3) expects the result to be updated in prop. assert(val == prop);Maybe you are thinking of something different, here is the code we're discussing: struct Foo { uint num; property ref uint front() { return num; } } -Stevethen you set through that ref. What you did is no different, you just delayed the assignment for a bit. You can reduce your test case to: (1) assign to the property. prop = val;Is not the same at all! prop = val will call the setter function, *ptr = val will not!
Jun 29 2010
On 06/28/2010 10:40 PM, dsimcha wrote:Once enforcement of property is enabled, we need to decide whether calling an property function using ()s should be legal. In other words, should property **require** omission of ()s or just allow it? My vote is for just allowing omission, because I've run into the following ambiguity while debugging std.range. Here's a reduced test case: struct Foo { uint num; property ref uint front() { return num; } } void main() { Foo foo; uint* bar = &foo.front; // Tries to return a delegate. } If I can assume that property functions can be called with explicit ()s to forcibly disambiguate this situation, then I can fix these kinds of bugs by simply doing a: uint* bar = &(foo.front()); Can we finalize the idea that this will continue to be allowed now so that I can fix the relevant bugs in Phobos and know that my fix won't be broken in a few compiler releases?I don't think it should be possible to take the address of a property. I also think applying property to normal fields would have special behavior. The effect would be a field that can't be addressed. Ideally this would be the default, to make it more intuitive to build flexible APIs, but I think we are too late for that bit of niceness. Just having that ability to build flexible APIs at all (in this case) by using property fields would be a good start. I wouldn't mind having some way to grab the delegate, but I think it should be very explicit. "This may break your code if the library writer changes their implementation" kinda explicit.
Jun 29 2010
On Monday, June 28, 2010 19:40:06 dsimcha wrote:Once enforcement of property is enabled, we need to decide whether calling an property function using ()s should be legal. In other words, should property **require** omission of ()s or just allow it? My vote is for just allowing omission, because I've run into the following ambiguity while debugging std.range. Here's a reduced test case: struct Foo { uint num; property ref uint front() { return num; } } void main() { Foo foo; uint* bar = &foo.front; // Tries to return a delegate. } If I can assume that property functions can be called with explicit ()s to forcibly disambiguate this situation, then I can fix these kinds of bugs by simply doing a: uint* bar = &(foo.front()); Can we finalize the idea that this will continue to be allowed now so that I can fix the relevant bugs in Phobos and know that my fix won't be broken in a few compiler releases?FWIW, TDPL says that you can't use the parens when using a property function. - Jonathan M Davis
Jun 29 2010