Thread overview | |||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
September 06, 2016 @property Incorrectly Implemented? | ||||
---|---|---|---|---|
| ||||
Currently it seems that @property isn't implemented correctly. For some reason when you try to get the pointer of a property it returns a delegate for some reason. This just seems plain wrong, the whole purpose of a property is for a function to behave as if it weren't a function. There's also some inconsistencies in the behavior, "get" is implemented one way and then "set" is implemented another. http://ideone.com/ZgGT2G &t.x // returns "ref int delegate()" &t.x() // ok returns "int*", but defeats purpose of @property &(t.j = 10) // shouldn't this return "ref int delegate(int)" ? It would be nice to get this behavior fixed, so that it doesn't become set in stone. I think returning a delegate pointer is not what people would except nor is there really any use case for it. |
September 06, 2016 Re: @property Incorrectly Implemented? | ||||
---|---|---|---|---|
| ||||
Posted in reply to John | On 09/06/2016 09:18 PM, John wrote: > &(t.j = 10) // shouldn't this return "ref int delegate(int)" ? `&t.j` should and does. With `= 10`, it's definitely a call, just like `&t.x()`. > It would be nice to get this behavior fixed, so that it doesn't become > set in stone. Unfortunately, it already kinda is. Just flipping the switch would break circa all D code in existence. That's deemed unacceptable by the leadership, as far as I know. If this can even be fixed, it must be done very carefully. The -property compiler switch is currently being deprecated. Maybe it can be repurposed later on to change behavior to your liking. But that's at least a couple releases in the future, i.e. months, maybe years. |
September 06, 2016 Re: @property Incorrectly Implemented? | ||||
---|---|---|---|---|
| ||||
Posted in reply to John | On Tuesday, September 06, 2016 19:18:11 John via Digitalmars-d wrote:
> Currently it seems that @property isn't implemented correctly. For some reason when you try to get the pointer of a property it returns a delegate for some reason. This just seems plain wrong, the whole purpose of a property is for a function to behave as if it weren't a function. There's also some inconsistencies in the behavior, "get" is implemented one way and then "set" is implemented another.
>
> http://ideone.com/ZgGT2G
>
> &t.x // returns "ref int delegate()"
> &t.x() // ok returns "int*", but defeats purpose of
> @property
> &(t.j = 10) // shouldn't this return "ref int delegate(int)"
> ?
>
> It would be nice to get this behavior fixed, so that it doesn't become set in stone. I think returning a delegate pointer is not what people would except nor is there really any use case for it.
Okay. How would it work to safely get a pointer to anything but the @property function when taking its address? &t.x() is just going to give you the address of the return value - which in most cases, is going to be a temporary, so if that even compiles in most cases, it's a bit scary. Sure, if the @property function returns by ref, then it can work, but an @property function which returns by ref isn't worth much, since you're then giving direct access to the member variable which is what an @property function is usually meant to avoid. If you wanted to do that, you could just use a public member variable.
So, given that most @property functions are not going to return by ref, how does it make any sense at all for taking the address of an @property function to do anything different than give you a delegate? Sure, that's not what happens when you take the address of a variable, but you're not dealing with a variable. You're dealing with an @property function which is just trying to emulate a variable.
The reality of the matter is that an @property function is _not_ a variable. It's just trying to emulate one, and that abstraction falls apart _really_ fast once you try and do much beyond getting and setting the value - e.g. passing by ref falls flat on its face. We could do better than currently do (e.g. making += lower to code that uses both the getter and the setter when the getter doesn't return by ref), but there are some areas where a property function simply can't act like a variable, because it isn't one. There isn't even a guarantee that an @property function is backed by memory. It could be a completely calculated value, in which case, expecting to get an address of a variable when taking the address of the @property function makes even less sense.
- Jonathan M Davis
|
September 06, 2016 Re: @property Incorrectly Implemented? | ||||
---|---|---|---|---|
| ||||
Posted in reply to John | On Tuesday, 6 September 2016 at 19:18:11 UTC, John wrote:
>
> Currently it seems that @property isn't implemented correctly. For some reason when you try to get the pointer of a property it returns a delegate for some reason. This just seems plain wrong, the whole purpose of a property is for a function to behave as if it weren't a function. There's also some inconsistencies in the behavior, "get" is implemented one way and then "set" is implemented another.
>
> http://ideone.com/ZgGT2G
>
> &t.x // returns "ref int delegate()"
> &t.x() // ok returns "int*", but defeats purpose of @property
> &(t.j = 10) // shouldn't this return "ref int delegate(int)" ?
>
> It would be nice to get this behavior fixed, so that it doesn't become set in stone. I think returning a delegate pointer is not what people would except nor is there really any use case for it.
With properties, the & operator is the only way to have the function itself and not it's return value. The reason is that the return value of a function is not necessarily an lvalue, so taking its address is not always correct. Imagine this:
@property int x() { return 3; }
As 3 is an rvalue, you cannot take its address. That's the difference between a true field and a computed one.
The purpose of properties is the following:
struct S
{
@property int x() { /* whatever */ }
int y() { /* whatever */ }
}
writeln(typeof(S.x).stringof); // prints int
writeln(typeof(S.y).stringof); // prints int delegate()
|
September 06, 2016 Re: @property Incorrectly Implemented? | ||||
---|---|---|---|---|
| ||||
Posted in reply to John | On 9/6/16 3:18 PM, John wrote:
>
> Currently it seems that @property isn't implemented correctly. For some
> reason when you try to get the pointer of a property it returns a
> delegate for some reason. This just seems plain wrong, the whole purpose
> of a property is for a function to behave as if it weren't a function.
> There's also some inconsistencies in the behavior, "get" is implemented
> one way and then "set" is implemented another.
>
> http://ideone.com/ZgGT2G
>
> &t.x // returns "ref int delegate()"
> &t.x() // ok returns "int*", but defeats purpose of @property
> &(t.j = 10) // shouldn't this return "ref int delegate(int)" ?
>
> It would be nice to get this behavior fixed, so that it doesn't become
> set in stone. I think returning a delegate pointer is not what people
> would except nor is there really any use case for it.
Just FYI, at the moment I believe the only difference (aside from the defunct -property switch) between a @property function and a non-@property function is:
int foo1() { return 1; }
@property int foo2() { return 1; }
pragma(msg, typeof(foo1)); // int function()
pragma(msg, typeof(foo2)); // int
That's it. typeof returns a different thing. All @property functions act just like normal functions when used in all other cases, and property syntax (assignment and getting) work on non-@property functions.
This situation is less than ideal. But it's been battled about dozens of times on the forums (including the very reasonable points you are making). It hasn't been solved, and the cynic in me says it won't ever be.
-Steve
|
September 07, 2016 Re: @property Incorrectly Implemented? | ||||
---|---|---|---|---|
| ||||
Posted in reply to John | On Tuesday, 6 September 2016 at 19:18:11 UTC, John wrote:
> It would be nice to get this behavior fixed.
Disagree. I've used properties before in C# to transform to and from data sets required for network multiplayer. It works functionally the same way in D. Behaviour is as I would expect for the wider implications of how properties can work.
|
September 07, 2016 Re: @property Incorrectly Implemented? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jonathan M Davis | On Tuesday, 6 September 2016 at 19:37:26 UTC, Jonathan M Davis wrote: > but an @property function which returns by ref isn't worth much, since you're then giving direct access to the member variable which is what an @property function is usually meant to avoid. If you wanted to do that, you could just use a public member variable. It can do lazy initialization, allow to set a breakpoint, log access etc. > You're dealing with an @property function which is just trying to emulate a variable. That's the whole point. It's trying to emulate a variable, so why not make it do it? |
September 07, 2016 Re: @property Incorrectly Implemented? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Kagamin | On Wednesday, September 07, 2016 08:15:43 Kagamin via Digitalmars-d wrote: > On Tuesday, 6 September 2016 at 19:37:26 UTC, Jonathan M Davis > > wrote: > > but an @property function which returns by ref isn't worth much, since you're then giving direct access to the member variable which is what an @property function is usually meant to avoid. If you wanted to do that, you could just use a public member variable. > > It can do lazy initialization, allow to set a breakpoint, log access etc. But if you return the value by ref, then you pretty much circumvent all of that, because then someone can do something like take the address of the return value and procede to mutate it whenever they want without hitting your breakpoint or log messages or any of that. You can do a few things that can't be done with a public member variable, but on the whole, returning by ref defeats the purpose of having a property function. And there are plenty of property functions that don't even refer to variables but instead are calculated, in which case there is no variable to return a ref to anyway. So, while some @property functions may return by ref, most won't, and it's arguably a bad idea in general. > > You're dealing with an @property function which is just trying to emulate a variable. > > That's the whole point. It's trying to emulate a variable, so why not make it do it? Because aside from a few basic operations, it's not possible. Stuff like assignment can be made to work, but something as simple as passing by ref falls simply cannot be done except in the case where the @property function returns by ref - which is not the normal case. And for a large percentage of property functions, you don't want it to be the case that taking the address of the property function gives you a pointer to a member variable. There are certainly some operations that we could better emulate with @property functions that currently don't work without returning by ref (like ++ or -=), but something like taking the address of the @property function simply isn't going to work in most cases, and neither is passing by ref. Basically, only stuff that can be lowered to calls to the getter and setter @property functions is going to work. Anything that would require an actual variable with an actual memory location isn't going to work unless the @property function returns by ref, and making taking the address of that kind of @property function give you the address of the variable would then not be consistent with any other @property function, which would create a different set of problems. It's nice that we can have property syntax rather than having to have functions that start with get and set, but it really doesn't work to fully emulate variables. - Jonathan M Davis |
September 07, 2016 Re: @property Incorrectly Implemented? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jonathan M Davis | On Wednesday, 7 September 2016 at 09:34:12 UTC, Jonathan M Davis wrote: > There are certainly some operations that we could better emulate with @property functions that currently don't work without returning by ref (like ++ or -=), but something like taking the address of the @property function simply isn't going to work in most cases, and neither is passing by ref. Basically, only stuff that can be lowered to calls to the getter and setter @property functions is going to work. > > It's nice that we can have property syntax rather than having to have functions that start with get and set, but it really doesn't work to fully emulate variables. > > - Jonathan M Davis BTW, some time ago, in another thread [1] about properties, we ended up writing this wrapper [2], which does a pretty good job at simulating fields. In the original thread you can also find other variants of it. [1] http://forum.dlang.org/thread/okmgnrhdoeciovrfjmaj@forum.dlang.org [2] http://pastebin.com/38n0fEtF |
September 07, 2016 Re: @property Incorrectly Implemented? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jonathan M Davis | An easy way around this would be to disallow taking the address of a property at all. Sure it introduces a disparity between properties and real member variables, but that's surely worth all the confusion that might be caused otherwise. Is it even that common to take the address of a member variable of an aggregate outside low-level code? |
Copyright © 1999-2021 by the D Language Foundation