www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - DIP26: properties defined

reply Robert <jfanatiker gmx.at> writes:
Ok. Here finally it is:

http://wiki.dlang.org/DIP26


Best regards,

Robert
Feb 08 2013
next sibling parent "Rob T" <alanb ucora.com> writes:
On Friday, 8 February 2013 at 23:53:40 UTC, Robert wrote:
 Ok. Here finally it is:

 http://wiki.dlang.org/DIP26


 Best regards,

 Robert
The definition is the obvious first step, so thanks for taking the time to define one. What we really need is a process in place for managing the language specification, otherwise we'll be spinning wheels forever. The concept of DIPs are not enough, for example there's no revision control over the specification, and no ability to determine what version of the specification a given compiler version adheres to. There's also not much going on for planning and prioritizing what needs to be done. A process for developing all aspects of the D language should be a top priority. --rt
Feb 08 2013
prev sibling next sibling parent reply "John Colvin" <john.loughran.colvin gmail.com> writes:
On Friday, 8 February 2013 at 23:53:40 UTC, Robert wrote:
 Ok. Here finally it is:

 http://wiki.dlang.org/DIP26


 Best regards,

 Robert
This seems a pretty straightforward approach. The less surprises and special cases the better. In short, good idea!
Feb 08 2013
next sibling parent "eles" <eles eles.com> writes:
On Saturday, 9 February 2013 at 00:27:04 UTC, John Colvin wrote:
 On Friday, 8 February 2013 at 23:53:40 UTC, Robert wrote:

 In short, good idea!
+1
Feb 08 2013
prev sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 02/09/2013 01:27 AM, John Colvin wrote:
 On Friday, 8 February 2013 at 23:53:40 UTC, Robert wrote:
 Ok. Here finally it is:

 http://wiki.dlang.org/DIP26


 Best regards,

 Robert
This seems a pretty straightforward approach. The less surprises and special cases the better. ...
"Taking the address of a property As this is illegal for properties..." property ref int foo(); int* y = &(&foo)();
Feb 08 2013
parent FG <home fgda.pl> writes:
On 2013-02-09 02:36, Timon Gehr wrote:
 "Taking the address of a property

 As this is illegal for properties..."

  property ref int foo();
 int* y = &(&foo)();
Yes, but this DIP makes it invalid to define a property ref T foo(). To use ref it would have to be a normal function: ref T foo(). So finally this example no longer ruins the property construct. :)
Feb 08 2013
prev sibling next sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 02/09/2013 12:53 AM, Robert wrote:
 Ok. Here finally it is:

 http://wiki.dlang.org/DIP26


 Best regards,

 Robert
"For optional parentheses, I would like to adopt the scheme already explained in DIP23." It is not actually explained. "DIP23 and DIP24 both don't seem to have a clear concept what properties actually are, resulting in rules that destroy their original purpose (For example forbidding module level properties)." That is a very strong claim to make and a very weak example.
Feb 08 2013
parent "Rob T" <alanb ucora.com> writes:
On Saturday, 9 February 2013 at 01:48:25 UTC, Timon Gehr wrote:
 On 02/09/2013 12:53 AM, Robert wrote:
 Ok. Here finally it is:

 http://wiki.dlang.org/DIP26


 Best regards,

 Robert
"For optional parentheses, I would like to adopt the scheme already explained in DIP23." It is not actually explained. "DIP23 and DIP24 both don't seem to have a clear concept what properties actually are, resulting in rules that destroy their original purpose (For example forbidding module level properties)." That is a very strong claim to make and a very weak example.
It's very clear that there is no definition of what a property is in either DIP23 or DIP24. The details are made up based on someones definition, but I cannot be certain what that definition that is, probably multiple definitions depending on who you ask. DIP23 firmly states that there are no module level properties that emulate global variables, and proposes a strange implementation that does not resemble what one would normally consider to be a property. If we had a clear definition of "property" in DIP23, I'd love to see how it would account for the two inconsistent behaviors. I think that a sensible definition would prevent such an inconsistent proposal from appearing in the first place. --rt
Feb 08 2013
prev sibling next sibling parent reply Michel Fortin <michel.fortin michelf.ca> writes:
On 2013-02-08 23:53:30 +0000, Robert <jfanatiker gmx.at> said:

 Ok. Here finally it is:
 
 http://wiki.dlang.org/DIP26
This is pretty much exactly how I think properties should work. There's two possible benefits you may to have overlooked… One benefit of the " property T foo;" syntax that does the boilerplate code for you over using a plain variable: the getter and setter generated are virtual in a class, so a derived class can override them. Doesn't work with a plain variable. Another possible benefit that we could have is the ability to use the default getter but to provide your own setter implementation by just declaring it: property int a; property void a(int value) { __a = value; refresh(); } Much cleaner than this: private int _a; property int a() { return _a; } property void a(int value) { _a = value; refresh(); } It's really great to not have to write boilerplate functions when default behaviour is perfectly fine. I've been using Objective-C for a while now and the recent changes where it automatically synthesize a variable, a getter, and a setter when declaring a property (unless you provide your own) are truly delightful. -- Michel Fortin michel.fortin michelf.ca http://michelf.ca/
Feb 08 2013
next sibling parent reply Marco Leise <Marco.Leise gmx.de> writes:
Am Fri, 8 Feb 2013 22:13:45 -0500
schrieb Michel Fortin <michel.fortin michelf.ca>:

 On 2013-02-08 23:53:30 +0000, Robert <jfanatiker gmx.at> said:
=20
 Ok. Here finally it is:
=20
 http://wiki.dlang.org/DIP26
=20 This is pretty much exactly how I think properties should work. There's=20 two possible benefits you may to have overlooked=E2=80=A6 =20 One benefit of the " property T foo;" syntax that does the boilerplate=20 code for you over using a plain variable: the getter and setter=20 generated are virtual in a class, so a derived class can override them.=20 Doesn't work with a plain variable. =20 Another possible benefit that we could have is the ability to use the=20 default getter but to provide your own setter implementation by just=20 declaring it: =20 property int a; property void a(int value) { __a =3D value; refresh(); } =20 Much cleaner than this: =20 private int _a; property int a() { return _a; } property void a(int value) { _a =3D value; refresh(); } =20 It's really great to not have to write boilerplate functions when=20 default behaviour is perfectly fine. I've been using Objective-C for a=20 while now and the recent changes where it automatically synthesize a=20 variable, a getter, and a setter when declaring a property (unless you=20 provide your own) are truly delightful.
There is only little think that itches me. In this example a is an int. Would the setter always take a copy of a large struct? I see no way to make it 'auto ref'! --=20 Marco
Feb 08 2013
next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Saturday, February 09, 2013 06:38:00 Marco Leise wrote:
 There is only little think that itches me. In this example a
 is an int. Would the setter always take a copy of a large
 struct? I see no way to make it 'auto ref'!
It would be simple enough to make it so that the compiler used auto ref in the lowered version and just make the variable itself int, though the DIP obviously doesn't say that. - Jonathan M Davis
Feb 08 2013
prev sibling parent Robert <jfanatiker gmx.at> writes:
On Fri, 2013-02-08 at 22:00 -0800, Jonathan M Davis wrote:
 It would be simple enough to make it so that the compiler used auto
 ref in the 
 lowered version and just make the variable itself int, though the DIP 
 obviously doesn't say that.
That would be impossible for virtual functions in a class. What the compiler could do, is simply provide both. This has to be thought through, what is important is that it is very clear what the compiler produces. As properties are meant to be assigned (which implies a copy at some point), you usually try to keep them small anyway or making them a class so that you only have to assign a reference. So I think it is not a bad choice to have the compiler simply generate the most simple trivial form, taking the argument by value. If you really want something different in some special application, you may still provide the functions on your own. Having said that, I really don't mind having the compiler produce both, if people think this is a good idea.
Feb 10 2013
prev sibling next sibling parent Dmitry Olshansky <dmitry.olsh gmail.com> writes:
09-Feb-2013 07:13, Michel Fortin пишет:
 On 2013-02-08 23:53:30 +0000, Robert <jfanatiker gmx.at> said:

 Ok. Here finally it is:

 http://wiki.dlang.org/DIP26
This is pretty much exactly how I think properties should work. There's two possible benefits you may to have overlooked… One benefit of the " property T foo;" syntax that does the boilerplate code for you over using a plain variable: the getter and setter generated are virtual in a class, so a derived class can override them. Doesn't work with a plain variable. Another possible benefit that we could have is the ability to use the default getter but to provide your own setter implementation by just declaring it: property int a; property void a(int value) { __a = value; refresh(); }
Yes, I too had thoughts along the same lines. Though just writing some setters by hand and then adding: mixin TrivialProperties!(_a, _b, _c); should be doable. But it would be still an ugly boilerplate.
 Much cleaner than this:

      private int _a;
       property int a() { return _a; }
       property void a(int value) { _a = value; refresh(); }

 It's really great to not have to write boilerplate functions when
 default behaviour is perfectly fine. I've been using Objective-C for a
 while now and the recent changes where it automatically synthesize a
 variable, a getter, and a setter when declaring a property (unless you
 provide your own) are truly delightful.
-- Dmitry Olshansky
Feb 08 2013
prev sibling next sibling parent reply "Tove" <tove fransson.se> writes:
On Saturday, 9 February 2013 at 03:13:47 UTC, Michel Fortin wrote:
 It's really great to not have to write boilerplate functions 
 when default behaviour is perfectly fine. I've been using 
 Objective-C for a while now and the recent changes where it 
 automatically synthesize a variable, a getter, and a setter 
 when declaring a property (unless you provide your own) are 
 truly delightful.
property int a; I would prefer if property simply disallows '&' then it doesn't have to be lowered into anything and can stay a field... if you later decide to add a "real" getter/setter, it still would be source compatible and you wouldn't have to refactor the source.
Feb 09 2013
parent Jacob Carlborg <doob me.com> writes:
On 2013-02-09 10:57, Tove wrote:

  property int a;

 I would prefer if  property simply disallows '&' then it doesn't have to
 be lowered into anything and can stay a field... if you later decide to
 add a "real" getter/setter, it still would be source compatible and you
 wouldn't have to refactor the source.
If it's not lowered to functions they won't be virtual, which might be wanted. -- /Jacob Carlborg
Feb 09 2013
prev sibling next sibling parent Robert <jfanatiker gmx.at> writes:
I am going to consider these. Thanks!
On Fri, 2013-02-08 at 22:13 -0500, Michel Fortin wrote:
 On 2013-02-08 23:53:30 +0000, Robert <jfanatiker gmx.at> said:
 
 Ok. Here finally it is:
 
 http://wiki.dlang.org/DIP26
This is pretty much exactly how I think properties should work. There's two possible benefits you may to have overlooked… One benefit of the " property T foo;" syntax that does the boilerplate code for you over using a plain variable: the getter and setter generated are virtual in a class, so a derived class can override them. Doesn't work with a plain variable. Another possible benefit that we could have is the ability to use the default getter but to provide your own setter implementation by just declaring it: property int a; property void a(int value) { __a = value; refresh(); } Much cleaner than this: private int _a; property int a() { return _a; } property void a(int value) { _a = value; refresh(); } It's really great to not have to write boilerplate functions when default behaviour is perfectly fine. I've been using Objective-C for a while now and the recent changes where it automatically synthesize a variable, a getter, and a setter when declaring a property (unless you provide your own) are truly delightful.
Feb 09 2013
prev sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2013-02-09 04:13, Michel Fortin wrote:

 This is pretty much exactly how I think properties should work. There's
 two possible benefits you may to have overlooked…

 One benefit of the " property T foo;" syntax that does the boilerplate
 code for you over using a plain variable: the getter and setter
 generated are virtual in a class, so a derived class can override them.
 Doesn't work with a plain variable.

 Another possible benefit that we could have is the ability to use the
 default getter but to provide your own setter implementation by just
 declaring it:

       property int a;
       property void a(int value) { __a = value; refresh(); }

 Much cleaner than this:

      private int _a;
       property int a() { return _a; }
       property void a(int value) { _a = value; refresh(); }

 It's really great to not have to write boilerplate functions when
 default behaviour is perfectly fine. I've been using Objective-C for a
 while now and the recent changes where it automatically synthesize a
 variable, a getter, and a setter when declaring a property (unless you
 provide your own) are truly delightful.
I completely agree, I really like it. Do we want to be able to use attributes like "final", and perhaps others, when declaring a property field: property final int a; The lowered functions would have the "final" attribute attached to them self. -- /Jacob Carlborg
Feb 09 2013
parent reply Michel Fortin <michel.fortin michelf.ca> writes:
On 2013-02-09 15:22:28 +0000, Jacob Carlborg <doob me.com> said:

 I completely agree, I really like it. Do we want to be able to use 
 attributes like "final", and perhaps others, when declaring a property 
 field:
 
  property final int a;
 
 The lowered functions would have the "final" attribute attached to them self.
That'd make a lot of sense. -- Michel Fortin michel.fortin michelf.ca http://michelf.ca/
Feb 09 2013
parent Robert <jfanatiker gmx.at> writes:
I already thought about this too, good enough that D choose not to use
final for const variables like Java does.

On Sat, 2013-02-09 at 12:54 -0500, Michel Fortin wrote:
 On 2013-02-09 15:22:28 +0000, Jacob Carlborg <doob me.com> said:
 
 I completely agree, I really like it. Do we want to be able to use 
 attributes like "final", and perhaps others, when declaring a property 
 field:
 
  property final int a;
 
 The lowered functions would have the "final" attribute attached to them self.
That'd make a lot of sense.
Feb 09 2013
prev sibling next sibling parent "Rob T" <alanb ucora.com> writes:
On Friday, 8 February 2013 at 23:53:40 UTC, Robert wrote:
 Ok. Here finally it is:

 http://wiki.dlang.org/DIP26


 Best regards,

 Robert
"Properties as defined in this DIP are a way of encapsulation of fields of an entity (class, struct, module) in a way that the class/struct/module can actually control the access and thus encapsulates it, such that the field in reality might not even exist or be in a different format than presented, ... " This part of the definition seems to be sensible: A property implementation that meets the encapsulation test has to prevent direct access to the underlying property variables so that access can be controlled. Unfortunately the current proposed implementation fails to meet the encapsulation test for structs and classes and also for globals inside modules because no matter if a field is marked private inside a class or struct, it is directly accessible from outside the class or struct within the same module, thus breaking encapsulation, therefore control is not assured, i.e., the property methods are easily circumvented from within the module. If we make an exception to the encapsulation definition and allow encapsulation to be circumvented only within the module level but not from outside the module, then module level properties can meet the encapsulation test since private globals are not accessible from outside, but that works only if module level properties are allowed, but I understand that the currently proposed implementation is in a conflict with UCFS, so another exception to the definition is needed to disallow module level properties only because the implementation is inadequate which seems absurd to have to do. In summary, the definition of property encapsulation is good, but to meet the definition, the property implementation is not adequate, and D will require the ability to mark variables as private at the module level (this is something I don't understand why we don't have). --rt
Feb 08 2013
prev sibling next sibling parent reply Dmitry Olshansky <dmitry.olsh gmail.com> writes:
09-Feb-2013 03:53, Robert пишет:
 Ok. Here finally it is:

 http://wiki.dlang.org/DIP26
NoUFCS for properties
 Properties protect the access to a field of an entity (class/struct/module),
 so they actually have to be defined within the entity they belong to, just as
a field would.
Rubbish. std.array: property auto front(T)(T[] arr) { return arr[0]; } -- Dmitry Olshansky
Feb 08 2013
parent reply FG <home fgda.pl> writes:
On 2013-02-09 08:19, Dmitry Olshansky wrote:
 NoUFCS for properties
 Properties protect the access to a field of an entity (class/struct/module),
 so they actually have to be defined within the entity they belong to, just as
 a field would.
Rubbish. std.array: property auto front(T)(T[] arr) { return arr[0]; }
Yeah, banning UFCS for properties is too farfetched.
Feb 08 2013
next sibling parent "Rob T" <alanb ucora.com> writes:
On Saturday, 9 February 2013 at 07:45:05 UTC, FG wrote:
 On 2013-02-09 08:19, Dmitry Olshansky wrote:
 NoUFCS for properties
 Properties protect the access to a field of an entity 
 (class/struct/module),
 so they actually have to be defined within the entity they 
 belong to, just as
 a field would.
Rubbish. std.array: property auto front(T)(T[] arr) { return arr[0]; }
Yeah, banning UFCS for properties is too farfetched.
This attempt to define a standard definition shows that the idea of a property means different things depending on the person you ask and what they are trying to accomplish. The current property implementation is no good for the encapsulation definition, however it is great for what the compiler currently implements, which are regular functions with (soon to be) enforced getter and setter syntax. If we also want encapsulating properties that emulate variables as much as possible, that's a different type of property from the type that does not encapsulate and try to fully emulate a variable. property simply cannot do both. What's missing is the ability to wrap true private internals into a property namespace. This idea was presented a few times already, as it appears to be a reasonable solution. I really don't see why we cannot implement the non-encapsulated property implementation, which is essentially what we already have except with enforced getter/setter syntax and weak variable emulation (its just a regular function), and later after the dust settles we implement a real property with true powers of encapsulation and more precise variable emulation, although not to replace property because it does a good job for what it is design to do. --rt
Feb 09 2013
prev sibling parent reply Robert <jfanatiker gmx.at> writes:
Has anyone actually read the DIP?

Simply don't call it property.
On Sat, 2013-02-09 at 08:45 +0100, FG wrote:
 On 2013-02-09 08:19, Dmitry Olshansky wrote:
 NoUFCS for properties
 Properties protect the access to a field of an entity (class/struct/module),
 so they actually have to be defined within the entity they belong to, just as
 a field would.
Rubbish. std.array: property auto front(T)(T[] arr) { return arr[0]; }
Yeah, banning UFCS for properties is too farfetched.
Feb 09 2013
parent reply FG <home fgda.pl> writes:
On 2013-02-09 12:32, Robert wrote:
 Has anyone actually read the DIP?

 Simply don't call it property.
Fine for getters but this time it will break things for setters: property void front(T)(T[] arr, T elem) {...} and either all code with assignments would have to be changed or assignments remain allowed for functions -- neither is good.
Feb 09 2013
parent reply Robert <jfanatiker gmx.at> writes:
As you can't actually encapsulate the array with free functions just do:

ref T front(T)(T[] arr);

There is no value in using an actual setter.

If you really want encapsulation, just do:

struct EncapsulatedArray(T) {
T front()  property;
void front(T value)  property;
private T[] arr_;
}

On Sat, 2013-02-09 at 12:43 +0100, FG wrote:
 On 2013-02-09 12:32, Robert wrote:
 Has anyone actually read the DIP?

 Simply don't call it property.
Fine for getters but this time it will break things for setters: property void front(T)(T[] arr, T elem) {...} and either all code with assignments would have to be changed or assignments remain allowed for functions -- neither is good.
Feb 09 2013
parent FG <home fgda.pl> writes:
On 2013-02-09 12:57, Robert wrote:
 As you can't actually encapsulate the array with free functions just do:

 ref T front(T)(T[] arr);

 There is no value in using an actual setter.
Ah, sorry, you're right. It's an lvalue, so no setter is needed.
Feb 09 2013
prev sibling next sibling parent reply "deadalnix" <deadalnix gmail.com> writes:
On Friday, 8 February 2013 at 23:53:40 UTC, Robert wrote:
 Ok. Here finally it is:

 http://wiki.dlang.org/DIP26


 Best regards,

 Robert
Taking the address of a property <= no. It I take the address of an int, I get an int* or an error because it is invalid. Not a delegate ! No UFCS for properties <= no. Behaviour like functions <= WTF should properties behave differently if the return a function ? This DIP is probably the worse as of now. The only thing that make sense is property T foo;
Feb 08 2013
parent Robert <jfanatiker gmx.at> writes:
On Sat, 2013-02-09 at 08:28 +0100, deadalnix wrote:
 Taking the address of a property  <= no. It I take the address of 
 an int, I get an int* or an error because it is invalid. Not a 
 delegate !
 No UFCS for properties <= no.
 Behaviour like functions <= WTF should properties behave 
 differently if the return a function ?
You are still thinking of properties as fields. Which does not work reliable in any proposal and actually can not, that is the reason for encapsulation in the first place. My arguments against UFCS for properties make a lot of sense if you think about it and result in a very clean implementation, with little breakage and the added benefit of actually having something that deserves to be called property. The other proposals try to solve the issue of functions returning functions being inconsistent across real functions and some property like thing that tries (badly) to mimic a field, by making property just more non sensical, instead of tackling the root cause of the problem: We can not mimic fields and in fact there is absolutely no reason to do so, if you think about it, you don't really want that, otherwise all books about OOP would be wrong.
Feb 09 2013
prev sibling next sibling parent "Michael" <pr m1xa.com> writes:
On Friday, 8 February 2013 at 23:53:40 UTC, Robert wrote:
 Ok. Here finally it is:

 http://wiki.dlang.org/DIP26


 Best regards,

 Robert
Why I should write fun()() when property returns a delegate? Additional () should not be necessary. Also combo properties like int get_set_IntValue(int) I think should be avoided.
Feb 09 2013
prev sibling parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Fri, 08 Feb 2013 18:53:30 -0500, Robert <jfanatiker gmx.at> wrote:

 Ok. Here finally it is:

 http://wiki.dlang.org/DIP26
Wow. So you simply want to go back to D1-style properties. It would have been simpler to just specify that we define a property like this: // this is a property int foo() {...} -Steve
Feb 09 2013
parent Robert <jfanatiker gmx.at> writes:
 // this is a property
 int foo() {...}
It is, if you consider properties to be functions that can be called without parentheses. Which is quite a lame definition of property if you ask me. But yeah my proposal makes properties to be considered functions, just with some guarantees regarding encapsulation and the special syntax that prop=a; means: prop(a); Actually Michel Fortin summarizes the DIP quite to the point:
 So in short, this proposal is that  property does only two things
when
 applied to a function: it enables the setter syntax and it changes
the
 overload rules.
 
In addition it restricts the setter syntax (prop=a) to be interpreted in a non UFCS way, meaning there will be no setter methods with two parameters. (Not accounting for the implicit this parameter)
Feb 10 2013