digitalmars.D - On DIP 23
- Robert (65/65) Feb 06 2013 Well first what I like about it: The approach function symbols are
- eles (7/8) Feb 07 2013 You're in the wrong spot of the world. Everywhere else outside
- Dicebot (4/13) Feb 07 2013 Heh, after that many topics and discussion I have started to
- Andrei Alexandrescu (3/18) Feb 07 2013 I felt we were getting somewhere.
- Dicebot (9/11) Feb 07 2013 Both yes and no at the same time.
- H. S. Teoh (15/29) Feb 07 2013 Agreed. I've mostly refrained from participating in the myriad of
- Zach the Mystic (5/18) Feb 08 2013 In writing my article about nested structs, I stumbled upon a
- Zach the Mystic (3/24) Feb 08 2013 By stumbled I mean I accidentally wrote it without knowing what I
- Robert (3/6) Feb 07 2013 Same feeling here. But I'll try to be constructive and I hope I find the
- Andrei Alexandrescu (6/15) Feb 07 2013 I think the sarcasm is uncalled for. We're doing our best here and our
- Robert (22/22) Feb 07 2013 Properties provide a means of access control to fields. (Range checks,
- FG (7/15) Feb 07 2013 Once again. Ref returns are commonly used in ranges.
- Robert (14/19) Feb 07 2013 Good point, but I think that this is pretty much a corner case where it
- Steven Schveighoffer (14/21) Feb 07 2013 @property ref T front(T[] arr) { return arr[0];}
- Andrei Alexandrescu (5/18) Feb 07 2013 I think the point we're making here with T* vs ref T is that most good
- Steven Schveighoffer (15/36) Feb 07 2013 That is fine, as long as it is possible, and NOT overly-complex. Think ...
- Andrei Alexandrescu (3/8) Feb 07 2013 I agree that shouldn't be a motivator. To me it's like, "hey, a perk!"
- Robert (16/27) Feb 07 2013 It depends on how we are going to define properties and with all the
- Robert (5/5) Feb 07 2013 Just to be clear here, with DIP23 in place, the syntax at the caller
- Steven Schveighoffer (4/9) Feb 07 2013 int delegate()[] arr;
- Robert (7/10) Feb 07 2013 That's part of the mess we are trying to clean up here? As of DIP 23,
- Timon Gehr (4/14) Feb 07 2013 I prefer DIP24.
- Steven Schveighoffer (8/18) Feb 07 2013 I don't understand the point here. Why would we want to be backwards
- eskimo (31/34) Feb 08 2013 Ok, forget backwards compatibility for a moment, it was just an
- Steven Schveighoffer (8/24) Feb 08 2013 I don't believe you. DIP23 has flaws. Care to explain? "just wrong"
- Robert (19/45) Feb 08 2013 I can't find anything about that front has to be a property here:
- Steven Schveighoffer (44/89) Feb 08 2013 Technically this is true. But the expectation is that r.front is a
- FG (9/19) Feb 08 2013 There may be nothing saying that r.front has to be a @property, but don'...
- Robert (2/4) Feb 08 2013 Exactly.
- Robert (33/100) Feb 08 2013 First of all, thanks for this very insight full discussion. I start to
- Steven Schveighoffer (68/165) Feb 09 2013 You are welcome! I also am learning things and shaping my opinions base...
- Robert (78/162) Feb 10 2013 Ok, at the very first I have to make clear that my DIP is about changing
- Timon Gehr (3/7) Feb 10 2013 Why does this justify a keyword? I think Walter's initial proposal of
- Robert (14/16) Feb 10 2013 Read the DIP? It is about encapsulation and making set functions
- Timon Gehr (10/30) Feb 10 2013 Perfectly possible without DIP26 and encapsulation can be violated using...
- Robert (2/6) Feb 10 2013 Provided we actually give properties this meaning in D, which is
- Steven Schveighoffer (65/195) Feb 10 2013 We don't need a feature to implement encapsulation, it's quite possible ...
- Robert (68/178) Feb 10 2013 We don't need it. -> Yes.
- Steven Schveighoffer (90/267) Feb 10 2013 It does not. @property as you have designed it does not "solve" any
- Andrei Alexandrescu (5/12) Feb 08 2013 There would be ambiguities with module level properties. A property with...
- deadalnix (4/20) Feb 08 2013 I think this was settled, allowing such property to only be a
- eles (9/15) Feb 07 2013 At least it caught a bit of attention... but I agree. Sorry.
Well first what I like about it: The approach function symbols are handled, it is a pretty clear concept: void f() { } f; f is a function, you can take the address of it and call it and that's it. So if you just write it down, it makes sense that it gets called. Not so for delegates, function objects, ... Sounds sane to me, I like it. About properties: In short, I died a little reading it. I know we have UFCS, but properties are meant to emulate a field, so the semantics should be as close to a field as possible. Ideally, identical. Especially the part about module level properties made me crazy: property double fun(int x, double y) { assert(x == 42 && y == 43); return y; } 42.fun = 43; reads to me: The integer 42 has a property called fun, which gets assigned 43??? If we special case properties, we might as well disallow UFCS for them, which makes sense, because you can not define a field external to an object either. So the proposal for module level properties, would be right exactly the other way round (emulating global variables): private int myCoolSetting_; property int myCoolSetting() { return myCoolSetting_; } property void myCoolSetting(int setting) { enforce(setting>0 && setting<10, "Invalid setting!"); myCoolSetting_=setting; } myCoolSetting=8; // Ok. That is what properties are all about. The part, about taking the address of a property, is fine as long as we allow fields to be declared with property as I already suggested, with the following semantics: property int a; would be lowered to: private int __a; property void a(int a_) { __a=a_; } property int a() { return __a; } in order to ensure that property declared fields and properties declared as functions do really have the same semantics. If you don't think about properties as fields, than I understand Walters suggestion about removing property completely and we could as well do it. UFCS with properties, makes little to no sense. Because well the name already suggests: "Uniform Function Calling Syntax", properties are not about calling functions. Allowing UFCS would offer the possibility of adding some kind of dynamic properties/fields to an object, but the code samples with integers and especially the problem with module level properties suggests that this causes more problems than it is worth. properties -> no UFCS and we have a sane world! Best regards, Robert P.S.: Things like int a = 4.2.truncated; do make sense, but UFCS and optional parentheses would do the trick too, so no need to abuse properties there.
Feb 06 2013
On Wednesday, 6 February 2013 at 22:10:29 UTC, Robert wrote:properties are meant to emulate a fieldYou're in the wrong spot of the world. Everywhere else outside the D community, the above assertion is held for true. In the D community, it is not. Yes, there are places like that, and you are trapped into one of those. For your sake, during your future staying in this place, think of " properties" as functions with calling particularities.
Feb 07 2013
On Thursday, 7 February 2013 at 14:44:36 UTC, eles wrote:On Wednesday, 6 February 2013 at 22:10:29 UTC, Robert wrote:Heh, after that many topics and discussion I have started to think it would have been better if initial proposal to remove them altogether succeeded.properties are meant to emulate a fieldYou're in the wrong spot of the world. Everywhere else outside the D community, the above assertion is held for true. In the D community, it is not. Yes, there are places like that, and you are trapped into one of those. For your sake, during your future staying in this place, think of " properties" as functions with calling particularities.
Feb 07 2013
On 2/7/13 10:55 AM, Dicebot wrote:On Thursday, 7 February 2013 at 14:44:36 UTC, eles wrote:I felt we were getting somewhere. AndreiOn Wednesday, 6 February 2013 at 22:10:29 UTC, Robert wrote:Heh, after that many topics and discussion I have started to think it would have been better if initial proposal to remove them altogether succeeded.properties are meant to emulate a fieldYou're in the wrong spot of the world. Everywhere else outside the D community, the above assertion is held for true. In the D community, it is not. Yes, there are places like that, and you are trapped into one of those. For your sake, during your future staying in this place, think of " properties" as functions with calling particularities.
Feb 07 2013
On Thursday, 7 February 2013 at 16:35:17 UTC, Andrei Alexandrescu wrote:I felt we were getting somewhere. AndreiBoth yes and no at the same time. Last proposals did a great job addressing different issues regarding property syntax and I somewhat like them in that sense. But they miss an important paragraph about what properties are supposed to be in D semantically, when they should be used and what problems they try to solve. So far design feels like it is syntax based as opposed to use case based.
Feb 07 2013
On Thu, Feb 07, 2013 at 07:55:22PM +0100, Dicebot wrote:On Thursday, 7 February 2013 at 16:35:17 UTC, Andrei Alexandrescu wrote:Agreed. I've mostly refrained from participating in the myriad of related threads, because I felt like a lot of it was just bikeshedding over what syntax should/shouldn't be allowed, what this or that syntax should/shouldn't mean, but there wasn't much consideration of *why* we're doing this in the first place, and whether / how the various proposals will get us there. Currently I feel like we're just making a gigantic mountain out of a molehill, whereas more important issues like reviewing Dmitri's std.uni replacement are being overlooked. T -- Valentine's Day: an occasion for florists to reach into the wallets of nominal lovers in dire need of being reminded to profess their hypothetical love for their long-forgotten.I felt we were getting somewhere. AndreiBoth yes and no at the same time. Last proposals did a great job addressing different issues regarding property syntax and I somewhat like them in that sense. But they miss an important paragraph about what properties are supposed to be in D semantically, when they should be used and what problems they try to solve. So far design feels like it is syntax based as opposed to use case based.
Feb 07 2013
On Thursday, 7 February 2013 at 18:55:23 UTC, Dicebot wrote:On Thursday, 7 February 2013 at 16:35:17 UTC, Andrei Alexandrescu wrote:In writing my article about nested structs, I stumbled upon a general definition of a property which may be of value here. "A property is a named set of overloaded operations on a piece of data which replaces the appearance of that data in code(™)."I felt we were getting somewhere. AndreiBoth yes and no at the same time. Last proposals did a great job addressing different issues regarding property syntax and I somewhat like them in that sense. But they miss an important paragraph about what properties are supposed to be in D semantically, when they should be used and what problems they try to solve. So far design feels like it is syntax based as opposed to use case based.
Feb 08 2013
On Friday, 8 February 2013 at 21:31:17 UTC, Zach the Mystic wrote:On Thursday, 7 February 2013 at 18:55:23 UTC, Dicebot wrote:By stumbled I mean I accidentally wrote it without knowing what I was doing.On Thursday, 7 February 2013 at 16:35:17 UTC, Andrei Alexandrescu wrote:In writing my article about nested structs, I stumbled upon a general definition of a property which may be of value here. "A property is a named set of overloaded operations on a piece of data which replaces the appearance of that data in code(™)."I felt we were getting somewhere. AndreiBoth yes and no at the same time. Last proposals did a great job addressing different issues regarding property syntax and I somewhat like them in that sense. But they miss an important paragraph about what properties are supposed to be in D semantically, when they should be used and what problems they try to solve. So far design feels like it is syntax based as opposed to use case based.
Feb 08 2013
Heh, after that many topics and discussion I have started to think it would have been better if initial proposal to remove them altogether succeeded.Same feeling here. But I'll try to be constructive and I hope I find the time to write yet another DIP about properties next week. UFCS and properties just don't go together.
Feb 07 2013
On 2/7/13 9:44 AM, eles wrote:On Wednesday, 6 February 2013 at 22:10:29 UTC, Robert wrote:I think the sarcasm is uncalled for. We're doing our best here and our intent is indeed to have properties emulate fields. Properties emulate fields, but they can't behave 100% like fields because if they did they'd be fields. Andreiproperties are meant to emulate a fieldYou're in the wrong spot of the world. Everywhere else outside the D community, the above assertion is held for true. In the D community, it is not. Yes, there are places like that, and you are trapped into one of those. For your sake, during your future staying in this place, think of " properties" as functions with calling particularities.
Feb 07 2013
Properties provide a means of access control to fields. (Range checks, only readable, only writable, triggering a signal on change, ...) So as posted a few times, taking the address of the ref return value of a property is of no value at all. If you want someone to be able to take the address of a field, you should make it simply public (without property), because the property accessor methods won't gain you anything in this case. Having said this, I think the solution to the & operator is pretty straight forward, it takes the address of the accessor function, which in fact might me useful at times, but it never takes the address of the return value. (This only applies to properties, for functions simply do something like &(func()) to get the address of the return value.) Tada. Problem solved :-) I can remember Adam D. Ruppe saying that he would rather have it hidden completely that the property is accessed by methods, so that taking the address of the function would not be possible. I have to say, that this does not feel right for a system programming language and it does not really improve things, especially with property fields. Instead of hiding that properties are functions, we hide that there might be a real field behind those properties. Best regards, Robert
Feb 07 2013
On 2013-02-07 19:05, Robert wrote:taking the address of the ref return value of a property is of no value at all. If you want someone to be able to take the address of a field, you should make it simply public (without property), because the property accessor methods won't gain you anything in this case.Once again. Ref returns are commonly used in ranges. I'd say that being able to take address of someRange.front is good for example for interoperability with external C libraries. Temporarily using a pointer here should be fine.Having said this, I think the solution to the & operator is pretty straight forward, it takes the address of the accessor function [...] Tada. Problem solved :-)Didn't solve the one mentioned above. So either I am wrong, you are wrong or range.front shouldn't be a property?
Feb 07 2013
Good point, but I think that this is pretty much a corner case where it occasionally might be useful, but it does not rectify the consequences: The moment you are allowed to take the address, you are stuck with the ref returning accessor and can not change it later to a get/set pair. An easy solution: auto a=myrange.front; someCFunc(&a); myrange.front=a; It is a little more to write, and maybe a tad slower (depending on the smartness of the compiler), but we maintain the property guarantees, which seems to me to be a very valuable goal. Best regards, Robert On Thu, 2013-02-07 at 19:43 +0100, FG wrote:Once again. Ref returns are commonly used in ranges. I'd say that being able to take address of someRange.front is good for example for interoperability with external C libraries. Temporarily using a pointer here should be fine.
Feb 07 2013
On Thu, 07 Feb 2013 13:05:50 -0500, Robert <jfanatiker gmx.at> wrote:Properties provide a means of access control to fields. (Range checks, only readable, only writable, triggering a signal on change, ...) So as posted a few times, taking the address of the ref return value of a property is of no value at all. If you want someone to be able to take the address of a field, you should make it simply public (without property), because the property accessor methods won't gain you anything in this case.property ref T front(T[] arr) { return arr[0];} Not being able to take an address of an array's front element is not a viable solution. The array range's business is not to restrict access to the first element, it's simply to conform to a certain API. This all comes down to an incorrect belief that properties are simply front ends for private variables. They are not, even when many languages make such things necessary or easy to implement (objective C comes to mind). There are plenty of different uses of properties, and redirecting access to another variable (as does the above function) is certainly a valid use. I don't think we should make rules that are focused on specific use cases while discarding or diminishing others. -Steve
Feb 07 2013
On 2/7/13 2:13 PM, Steven Schveighoffer wrote:On Thu, 07 Feb 2013 13:05:50 -0500, Robert <jfanatiker gmx.at> wrote:I think the point we're making here with T* vs ref T is that most good work could and should be done with references that have provable scoping. Needing the actual address of something should not be casual. AndreiProperties provide a means of access control to fields. (Range checks, only readable, only writable, triggering a signal on change, ...) So as posted a few times, taking the address of the ref return value of a property is of no value at all. If you want someone to be able to take the address of a field, you should make it simply public (without property), because the property accessor methods won't gain you anything in this case.property ref T front(T[] arr) { return arr[0];} Not being able to take an address of an array's front element is not a viable solution. The array range's business is not to restrict access to the first element, it's simply to conform to a certain API.
Feb 07 2013
On Thu, 07 Feb 2013 15:14:22 -0500, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:On 2/7/13 2:13 PM, Steven Schveighoffer wrote:That is fine, as long as it is possible, and NOT overly-complex. Think of it like casting. Casting is essentially a no-op for performance, but is possible, explicit (well, *mostly* explicit), and straightforward. I don't see the problem with restricting address-taking of ref parameters or return values to system code. Well, other than making it less attractive to code in safe mode, but then again, I don't see myself using it much the way it is now. Most certainly, we should not outlaw taking the address of ref parameters because it's "hard" to solve the problem of getting property delegates (but only as long as people insist that adding to __traits is taboo). That was MY point. Your "solving" a problem by ignoring it, and also causing 10 problems elsewhere. -SteveOn Thu, 07 Feb 2013 13:05:50 -0500, Robert <jfanatiker gmx.at> wrote:I think the point we're making here with T* vs ref T is that most good work could and should be done with references that have provable scoping. Needing the actual address of something should not be casual.Properties provide a means of access control to fields. (Range checks, only readable, only writable, triggering a signal on change, ...) So as posted a few times, taking the address of the ref return value of a property is of no value at all. If you want someone to be able to take the address of a field, you should make it simply public (without property), because the property accessor methods won't gain you anything in this case.property ref T front(T[] arr) { return arr[0];} Not being able to take an address of an array's front element is not a viable solution. The array range's business is not to restrict access to the first element, it's simply to conform to a certain API.
Feb 07 2013
On 2/7/13 4:07 PM, Steven Schveighoffer wrote:Most certainly, we should not outlaw taking the address of ref parameters because it's "hard" to solve the problem of getting property delegates (but only as long as people insist that adding to __traits is taboo). That was MY point. Your "solving" a problem by ignoring it, and also causing 10 problems elsewhere.I agree that shouldn't be a motivator. To me it's like, "hey, a perk!" Andrei
Feb 07 2013
It depends on how we are going to define properties and with all the arguments in the discussions it seems to me that the only sane way to design properties is as simple front ends for private fields (which is my understanding of properties anyway). But with optional parantheses the property would also not be necessary for this case. So such use cases would need to be handled by normal functions. It would simply not be a property by definition. Redirecting access would not be the purpose of properties but for functions returning refs. And you are free to take the address then with &arr.front().property ref T front(T[] arr) { return arr[0];}Do you have any other UFCS examples, where property would seem to be appropriate?This all comes down to an incorrect belief that properties are simply front ends for private variables. They are not, even when many languages make such things necessary or easy to implement (objective C comes to mind). There are plenty of different uses of properties, and redirecting access to another variable (as does the above function) is certainly a valid use. I don't think we should make rules that are focused on specific use cases while discarding or diminishing others.It all depends on definitions. If you define an integer as an integral type, you would not expect it to do floating point arithmetic. Although there are use cases for floating point operations, but an integer is just the wrong tool for it.
Feb 07 2013
Just to be clear here, with DIP23 in place, the syntax at the caller side for: property ref T front(T[] arr) { return arr[0];} would not change if you remove the property. So little code breakage here and the code that breaks is easily fixed by removing property.
Feb 07 2013
On Thu, 07 Feb 2013 15:57:56 -0500, Robert <jfanatiker gmx.at> wrote:Just to be clear here, with DIP23 in place, the syntax at the caller side for: property ref T front(T[] arr) { return arr[0];} would not change if you remove the property. So little code breakage here and the code that breaks is easily fixed by removing property.int delegate()[] arr; arr.front(); -Steve
Feb 07 2013
On Thu, 2013-02-07 at 16:08 -0500, Steven Schveighoffer wrote:int delegate()[] arr; arr.front();That's part of the mess we are trying to clean up here? As of DIP 23, you would have to do arr.front()() in order to actually call the delegate. The current behaviour is also that you have to do arr.front()() in order to actually call the function. So with DIP23 in effect you would actually have to remove property in order to be backwards compatible.
Feb 07 2013
On 02/07/2013 10:28 PM, Robert wrote:On Thu, 2013-02-07 at 16:08 -0500, Steven Schveighoffer wrote:Of course.int delegate()[] arr; arr.front();That's part of the mess we are trying to clean up here?As of DIP 23, you would have to do arr.front()() in order to actually call the delegate.I prefer DIP24.The current behaviour is also that you have to do arr.front()() in order to actually call the function. So with DIP23 in effect you would actually have to remove property in order to be backwards compatible.Nobody wants to be backwards compatible in this regard.
Feb 07 2013
On Thu, 07 Feb 2013 16:28:42 -0500, Robert <jfanatiker gmx.at> wrote:On Thu, 2013-02-07 at 16:08 -0500, Steven Schveighoffer wrote:Not with propertyint delegate()[] arr; arr.front();That's part of the mess we are trying to clean up here? As of DIP 23, you would have to do arr.front()() in order to actually call the delegate.The current behaviour is also that you have to do arr.front()() in order to actually call the function. So with DIP23 in effect you would actually have to remove property in order to be backwards compatible.I don't understand the point here. Why would we want to be backwards compatible with a buggy compiler? In a bug-free implementation of arrays-as-ranges, arr[0] and arr.front should be perfectly interchangeable (with the well-known exception of strings). -Steve
Feb 07 2013
Ok, forget backwards compatibility for a moment, it was just an additional goody. On Thu, 2013-02-07 at 19:38 -0500, Steven Schveighoffer wrote:Not with propertyThat's the point, it would no longer be a property but a simple function returning ref. front for arrays would not be a property for two reasons: 1. front is a UFCS function, I think supporting UFCS with properties is just getting it wrong, have a look at DIP 23 if you don't believe me. 2. My current version, would not allow properties to return ref, but instead a property is a property if it defines a getter or a setter or both with the following exact definition: property void a(T val); property T a(); Everything that does not match these requirements can no longer be a property. With this restrictions in place, properties cause no problems, everything works as expected, no weird corner cases. These restrictions happen to establish property semantics that match the field hiding pattern and this is what properties are all about, if you ask me. The moment we stop trying making properties something they aren't, everything works out. With optional parentheses in place, accessors to fields via a ref are still possible, they just no longer conform to the property specification and thus can not be marked with property. (And don't need to be, because: arr.front=something; and something=arr.front; both still would work) The gain of this? Clear semantics. If I have a property and I can write access it, I know that there is a set function. If I have a property I can read, there has to be a getter. If it is no property, I don't have any guarantees, which might be fine, depending on the API. (E.g. for your arr.front example).
Feb 08 2013
On Fri, 08 Feb 2013 10:28:14 -0500, eskimo <jfanatiker gmx.at> wrote:Ok, forget backwards compatibility for a moment, it was just an additional goody. On Thu, 2013-02-07 at 19:38 -0500, Steven Schveighoffer wrote:Then it doesn't conform to the range API, where front is a property.Not with propertyThat's the point, it would no longer be a property but a simple function returning ref.front for arrays would not be a property for two reasons: 1. front is a UFCS function, I think supporting UFCS with properties is just getting it wrong, have a look at DIP 23 if you don't believe me.I don't believe you. DIP23 has flaws. Care to explain? "just wrong" isn't an explanation.2. My current version, would not allow properties to return ref, but instead a property is a property if it defines a getter or a setter or both with the following exact definition: property void a(T val); property T a();This is a severe reduction in expression, we should not be looking for extra ways to invalidate existing code unless there is an extremely good reason. "Just wrong" is not it. -Steve
Feb 08 2013
On Fri, 2013-02-08 at 12:52 -0500, Steven Schveighoffer wrote:Then it doesn't conform to the range API, where front is a property.I can't find anything about that front has to be a property here: http://dlang.org/phobos/std_range.html#isInputRange all it states that you can get the current element by issuing: r.front which would still be possible with the optional parentheses of DIP23.Look at the section "No module-level properties". Why not?! That's a perfectly valid use of properties. The proposal disallows module-level properties, but instead allows: 42.fun = 43; which reads like: assign 43 to the fun property of 42. We get this really obscure feature but disallowing module-level properties? If that is not wrong, than I don't know what is.front for arrays would not be a property for two reasons: 1. front is a UFCS function, I think supporting UFCS with propertiesisjust getting it wrong, have a look at DIP 23 if you don't believeme. I don't believe you. DIP23 has flaws. Care to explain? "just wrong" isn't an explanation.I have really good reasons and I hope I'll explain them well enough in the DIP I am currently writing. You already suggested that keeping compatibility to a broken implementation is not worth it, simply removing the property in cases where there are no longer allowed, seems not too hard a change to me, especially if we agree that we have to break compatibility in one way or the other.2. My current version, would not allow properties to return ref, but instead a property is a property if it defines a getter or a setterorboth with the following exact definition: property void a(T val); property T a();This is a severe reduction in expression, we should not be looking for extra ways to invalidate existing code unless there is an extremely good reason. "Just wrong" is not it.
Feb 08 2013
On Fri, 08 Feb 2013 14:05:40 -0500, Robert <jfanatiker gmx.at> wrote:On Fri, 2013-02-08 at 12:52 -0500, Steven Schveighoffer wrote:Technically this is true. But the expectation is that r.front is a property/field, not a function. That aspect is difficult to capture in a template, especially in the current implementation where property on a getter is essentially redundant info. In fact, the only case where a properly-implemented property would be required on a getter is for delegate properties. I would argue that if property worked correctly, it would be possible and correct to require r.front to be a property in that template.Then it doesn't conform to the range API, where front is a property.I can't find anything about that front has to be a property here: http://dlang.org/phobos/std_range.html#isInputRange all it states that you can get the current element by issuing: r.front which would still be possible with the optional parentheses of DIP23.Module level properties pose an issue, because property does not designate whether a property is a getter or a setter. In particular, a single-arg property function could be considered both a module property setter, or a UFCS property getter. So your issue is not really that UFCS properties are wrong, it's that disabling module-level properties is wrong. I agree with you, but at the same time, module level properties are not as common or useful as UFCS. In fact, one could argue they are more confusing since module scope is one of the only scopes that can be obscured. There are other possible solutions, such as designating something as a getter specifically, or adding more syntax (i.e. decorating the first parameter as 'this' for a module-level UFCS getter). But for now, the easiest thing is to disallow one or the other, and since UFCS properties are pretty much essential in Phobos, he's disabling the module level properties. The 42.fun = 43 example, just about everything is wrong with that. Look here is another function that D "allows": void increment(int x); What is that exactly supposed to do? 42.increment(); // what? increment(42); // what? Design and naming of functions is never going to be a problem that the compiler can solve.Look at the section "No module-level properties". Why not?! That's a perfectly valid use of properties. The proposal disallows module-level properties, but instead allows: 42.fun = 43; which reads like: assign 43 to the fun property of 42. We get this really obscure feature but disallowing module-level properties? If that is not wrong, than I don't know what is.front for arrays would not be a property for two reasons: 1. front is a UFCS function, I think supporting UFCS with propertiesisjust getting it wrong, have a look at DIP 23 if you don't believeme. I don't believe you. DIP23 has flaws. Care to explain? "just wrong" isn't an explanation.My point on that was, if something works but is not supposed to, we shouldn't have to worry about keeping that code working. property in its current form is NOT implemented as it was designed. There is no requirement to keep existing behavior that doesn't correctly work. In the example given, property is supposed to ban the use of parentheses according to the spec, but it doesn't. In fact, in the case of a property that returns a delegate, it REQUIRES the extra parentheses. This is a bug, and not something to try and keep working. On the other hand, ref properties is NOT a bug, it functions as designed. Whether to remove it or not is certainly a discussion we can have, but it's not buggy behavior. See the difference? -SteveI have really good reasons and I hope I'll explain them well enough in the DIP I am currently writing. You already suggested that keeping compatibility to a broken implementation is not worth it, simply removing the property in cases where there are no longer allowed, seems not too hard a change to me, especially if we agree that we have to break compatibility in one way or the other.2. My current version, would not allow properties to return ref, but instead a property is a property if it defines a getter or a setterorboth with the following exact definition: property void a(T val); property T a();This is a severe reduction in expression, we should not be looking for extra ways to invalidate existing code unless there is an extremely good reason. "Just wrong" is not it.
Feb 08 2013
On 2013-02-08 21:13, Steven Schveighoffer wrote:There may be nothing saying that r.front has to be a property, but don't forget setters. There are many examples of the following statement: r.front = val; Just look at the sources: grep -R "\.front = " ./src/phobos/ General agreement is that plain functions shouldn't be allowed to be called like setters, with assignment operator. So what now? Should all that code be changed to use r.front(val) instead? Or should void front(T val) remain a property, while ref T front() becomes a plain function?I can't find anything about that front has to be a property here: http://dlang.org/phobos/std_range.html#isInputRange all it states that you can get the current element by issuing: r.front which would still be possible with the optional parentheses of DIP23.Technically this is true. But the expectation is that r.front is a property/field, not a function. That aspect is difficult to capture in a template, especially in the current implementation where property on a getter is essentially redundant info.
Feb 08 2013
On Fri, 2013-02-08 at 22:15 +0100, FG wrote:Or should void front(T val) remain a property, while ref T front() becomes a plain function?Exactly.
Feb 08 2013
First of all, thanks for this very insight full discussion. I start to understand the other side. :-) On Fri, 2013-02-08 at 15:13 -0500, Steven Schveighoffer wrote:On Fri, 08 Feb 2013 14:05:40 -0500, Robert <jfanatiker gmx.at> wrote:In a template you should not care what it actually is, as long as this works: auto h=r.front; (stolen from the implementation of isForwardRange), if I understood your argument correctly.On Fri, 2013-02-08 at 12:52 -0500, Steven Schveighoffer wrote:Technically this is true. But the expectation is that r.front is a property/field, not a function. That aspect is difficult to capture in a template, especially in the current implementation where property on a getter is essentially redundant info.Then it doesn't conform to the range API, where front is a property.I can't find anything about that front has to be a property here: http://dlang.org/phobos/std_range.html#isInputRange all it states that you can get the current element by issuing: r.front which would still be possible with the optional parentheses of DIP23.In fact, the only case where a properly-implemented property would be required on a getter is for delegate properties. I would argue that if property worked correctly, it would be possible and correct to require r.front to be a property in that template.I don't understand, what is the exact problem with: r.front()()? Despite not matching the specification regarding no parentheses for properties?Module level properties pose an issue, because property does not designate whether a property is a getter or a setter. In particular, a single-arg property function could be considered both a module property setter, or a UFCS property getter. So your issue is not really that UFCS properties are wrong, it's that disabling module-level properties is wrong. I agree with you, but at the same time, module level properties are not as common or useful as UFCS.Sure UFCS for functions, I suggest that UFCS for properties does not make a lot of sense. (If you apply my definition of a property and accept simple functions with optional parentheses as better way.) I am sorry, I don't understand what you mean here with:In fact, one could argue they are more confusing since module scope is one of the only scopes that can be obscured.There are other possible solutions, such as designating something as a getter specifically, or adding more syntax (i.e. decorating the first parameter as 'this' for a module-level UFCS getter). But for now, the easiest thing is to disallow one or the other, and since UFCS properties are pretty much essential in Phobos, he's disabling the module level properties. The 42.fun = 43 example, just about everything is wrong with that. Look here is another function that D "allows": void increment(int x); What is that exactly supposed to do? 42.increment(); // what? increment(42); // what? Design and naming of functions is never going to be a problem that the compiler can solve.Point taken. But my point is, that with optional parentheses UFCS properties are not needed, so the cleaner solution is to forbid UFCS properties. (See my DIP for further reasoning when it is ready)My point on that was, if something works but is not supposed to, we shouldn't have to worry about keeping that code working. property in its current form is NOT implemented as it was designed. There is no requirement to keep existing behavior that doesn't correctly work. In the example given, property is supposed to ban the use of parentheses according to the spec, but it doesn't. In fact, in the case of a property that returns a delegate, it REQUIRES the extra parentheses. This is a bug, and not something to try and keep working.Despite being inconsistent with the specification, what are the problems with that?On the other hand, ref properties is NOT a bug, it functions as designed. Whether to remove it or not is certainly a discussion we can have, but it's not buggy behavior. See the difference?But the documentation of properties: http://dlang.org/property.html in the section about user defined properties also states in the very first sentence: Properties are functions that can be syntactically treated as if they were fields or variables. which is clearly not true at the moment. If this sentence got removed and replaced with a big fat warning that properties are not exchangeable with fields, this would be the least that should be done. The current thinking instead seems to be that properties are just syntactic sugar and the level of encapsulation is business that is left to the developer. My thinking on the other hand is, that properties are the method of encapsulation, so they should ensure it. If something does not, it is not a property, which leads to a very clean design of properties.
Feb 08 2013
On Fri, 08 Feb 2013 16:45:58 -0500, Robert <jfanatiker gmx.at> wrote:First of all, thanks for this very insight full discussion. I start to understand the other side. :-)You are welcome! I also am learning things and shaping my opinions based on these discussions.On Fri, 2013-02-08 at 15:13 -0500, Steven Schveighoffer wrote:In the grand scheme of things, the fact that a range's front accessor is a property or a function is not technically important. But front being a property IS important for specific uses. You can't have it so that front is a function only when using it as a range, and a property when using it as a delegate getter.On Fri, 08 Feb 2013 14:05:40 -0500, Robert <jfanatiker gmx.at> wrote:In a template you should not care what it actually is, as long as this works: auto h=r.front; (stolen from the implementation of isForwardRange), if I understood your argument correctly.all it states that you can get the current element by issuing: r.front which would still be possible with the optional parentheses of DIP23.Technically this is true. But the expectation is that r.front is a property/field, not a function. That aspect is difficult to capture in a template, especially in the current implementation where property on a getter is essentially redundant info.The problem is, isInputRange does not require that it is a function, but you ARE requiring that by specifying arbitrary rules. Imagine an infinite range (one which never ends), that returns exactly a specific delegate. Such a range could be implemented: struct infiniteDelegate { int delegate() front; enum empty = false; void popFront() {}; } Such a range would fit the definition of input range, but unlike an array, r.front() is how you call the delegate, not r.front()(). Making a consistent interface is not possible without property.In fact, the only case where a properly-implemented property would be required on a getter is for delegate properties. I would argue that if property worked correctly, it would be possible and correct to require r.front to be a property in that template.I don't understand, what is the exact problem with: r.front()()? Despite not matching the specification regarding no parentheses for properties?Actually, that is not true. Check out the definition of hasAssignableElements: By your requirements, hasAssignableElements!(T[]) would necessarily always be false, since UFCS properties are banned, so array.front is not a property. You are saying, I can't assign to the front element of an array. That doesn't sit well with the rest of array's API.Module level properties pose an issue, because property does not designate whether a property is a getter or a setter. In particular, a single-arg property function could be considered both a module property setter, or a UFCS property getter. So your issue is not really that UFCS properties are wrong, it's that disabling module-level properties is wrong. I agree with you, but at the same time, module level properties are not as common or useful as UFCS.Sure UFCS for functions, I suggest that UFCS for properties does not make a lot of sense. (If you apply my definition of a property and accept simple functions with optional parentheses as better way.)I am sorry, I don't understand what you mean here with:int x; void foo() { int x; // allowed x = 5; // applies to local scope, not module { int x; // error! shadows outer scope x. } } So the point is, a global property could possibly be obscured if you declared a local variable with the same name. Note also that you can have struct-qualified properties (at least you should be able to, it seems Andrei's DIP does not allow it, but it's not at odds with UFCS). Those are just about equivalent to module-level properties, they just require specifying the struct name (and people have used this in clever ways to achieve good readable results).In fact, one could argue they are more confusing since module scope is one of the only scopes that can be obscured.What about setters?There are other possible solutions, such as designating something as a getter specifically, or adding more syntax (i.e. decorating the first parameter as 'this' for a module-level UFCS getter). But for now, the easiest thing is to disallow one or the other, and since UFCS properties are pretty much essential in Phobos, he's disabling the module level properties. The 42.fun = 43 example, just about everything is wrong with that. Look here is another function that D "allows": void increment(int x); What is that exactly supposed to do? 42.increment(); // what? increment(42); // what? Design and naming of functions is never going to be a problem that the compiler can solve.Point taken. But my point is, that with optional parentheses UFCS properties are not needed, so the cleaner solution is to forbid UFCS properties. (See my DIP for further reasoning when it is ready)I'm not saying it's a problem, I suppose it could be considered by some, desirable to require the extra parentheses. I haven't heard from that person yet. But "being backwards compatible" is not a good reason when you are talking about incorrect behavior. It would have to be because that is a desirable feature. Frankly, if that was the case, I think we would never have introduced property.My point on that was, if something works but is not supposed to, we shouldn't have to worry about keeping that code working. property in its current form is NOT implemented as it was designed. There is no requirement to keep existing behavior that doesn't correctly work. In the example given, property is supposed to ban the use of parentheses according to the spec, but it doesn't. In fact, in the case of a property that returns a delegate, it REQUIRES the extra parentheses. This is a bug, and not something to try and keep working.Despite being inconsistent with the specification, what are the problems with that?It certainly is true. They can be treated like fields for getting and setting, and I think "syntactically" means you access them like you would access a field. You might say "yeah, but you can't do ++ on them!", but you can't do that to a const field either. Should const fields be considered fields? A ref property pretty much behaves EXACTLY like a field.On the other hand, ref properties is NOT a bug, it functions as designed. Whether to remove it or not is certainly a discussion we can have, but it's not buggy behavior. See the difference?But the documentation of properties: http://dlang.org/property.html in the section about user defined properties also states in the very first sentence: Properties are functions that can be syntactically treated as if they were fields or variables. which is clearly not true at the moment. If this sentence got removed and replaced with a big fat warning that properties are not exchangeable with fields, this would be the least that should be done.The current thinking instead seems to be that properties are just syntactic sugar and the level of encapsulation is business that is left to the developer.I don't think that SHOULD be D's business. Encapsulation should be possible, encouraged, but not dictated.My thinking on the other hand is, that properties are the method of encapsulation, so they should ensure it. If something does not, it is not a property, which leads to a very clean design of properties.Such a design is entirely possible today, even if ref properties exist, even if *properties* didn't exist. Why must you use ref properties just because they are available? Note that the reader/user of code is never guaranteed that they are working with properly encapsulated code. A property looks like a field, and a field is NOT encapsulated. So any compiler/language guarantees of encapsulation with properties are moot. -Steve
Feb 09 2013
Ok, at the very first I have to make clear that my DIP is about changing the actual specification, not trying to make the implementation to match the specification, because in my view of things, the specification is the problem. Properties in my proposal are no longer about optional parentheses ore forbidden parentheses. Properties are a concept hat benefits from the fact, that parentheses are optional, but would work either way. Reducing properties to functions with no parentheses is just not getting it right as we can see with the problems we have.In the grand scheme of things, the fact that a range's front accessor is a property or a function is not technically important. But front being a property IS important for specific uses. You can't have it so that front is a function only when using it as a range, and a property when using it as a delegate getter.In my DIP a property is a function and they behave the same, except that prop=5; calls prop(5); if prop is a property.I think this has to be fixed, because it solves all ambiguities and encourages good design.The problem is, isInputRange does not require that it is a function, but you ARE requiring that by specifying arbitrary rules.In fact, the only case where a properly-implemented property would be required on a getter is for delegate properties. I would argue that if property worked correctly, it would be possible and correct to require r.front to be a property in that template.I don't understand, what is the exact problem with: r.front()()? Despite not matching the specification regarding no parentheses for properties?Imagine an infinite range (one which never ends), that returns exactly a specific delegate. Such a range could be implemented: struct infiniteDelegate { int delegate() front; enum empty = false; void popFront() {}; }It would, based on the current definition, yes. But what is it good for? Why not simply write: struct infiniteDelegate { int delegate() front(); bool empty() property { return false; } void popFront() {}; } Where the body of front for example can ensure that the delegate is actually set and not null or can change it if necessary, ... I haven't applied property to front in this example, because it would not change anything, it would be required though if you provided a setter and wanted to have front=something; work. Whether or not you apply property to read-only functions, depends on your use case, if you want proper encapsulation, you would add property and in case you want a writable front at some time, you would add a setter. If you don't consider encapsulation necessary, you would probably do not add property and return a ref if it has to be writable sometime.Actually, that is not true. Check out the definition of hasAssignableElements: By your requirements, hasAssignableElements!(T[]) would necessarily always be false, since UFCS properties are banned, so array.front is not a property. You are saying, I can't assign to the front element of an array. That doesn't sit well with the rest of array's API.Not true, the current definition of front for arrays is: property ref T front(T)(T[] a); which would still work just the same, if you removed property. Strings are interesting as front returns a non ref dchar (obviously), but they have no writable front anyway. If you would really have a use case where you need an actual setter/getter for an array for example, just do proper encapsulation in a struct/class. If you don't do that, your setter could be bypassed anyway so the design is questionable at best. (Which you could still achieve via alias this, if you really wanted that.)void foo() { int x; // allowed x = 5; // applies to local scope, not module { int x; // error! shadows outer scope x. } } So the point is, a global property could possibly be obscured if you declared a local variable with the same name.Same for instance variables and member functions.Note also that you can have struct-qualified properties (at least you should be able to, it seems Andrei's DIP does not allow it, but it's not at odds with UFCS). Those are just about equivalent to module-level properties, they just require specifying the struct name (and people have used this in clever ways to achieve good readable results).Hmm, no real difference to struct/class properties: import std.stdio; int i; void main() { int i; i=8; writeln(".i: ", .i); writeln(".i: ", testglobal.i); } Prints 0 both times. (The file was named testglobal.d)It certainly is true. They can be treated like fields for getting and setting, and I think "syntactically" means you access them like you would access a field. You might say "yeah, but you can't do ++ on them!", but you can't do that to a const field either. Should const fields be considered fields?Well that's probably what was meant by this statement, but obviously it was misunderstood by me and many others. It suggests that you can use public fields if you would have required trivial set/get methods. (I even found a blog post by someone who was bashing against Java how silly they are and how cool D is, because we don't need trival set/get methods)A ref property pretty much behaves EXACTLY like a field.Exactly that is why I don't consider it a property. :-)It is not dictated, it is just encouraged and possible. If you don't need encapsulation, don't call it a property. Nothing changes. You even have a way out, if you first considered it a property with proper set/get and later on you decide that this is not really needed, you can drop it, no code will break, you just can not go back. But that was your decision the moment you gave up property.The current thinking instead seems to be that properties are just syntactic sugar and the level of encapsulation is business that is left to the developer.I don't think that SHOULD be D's business. Encapsulation should be possible, encouraged, but not dictated.You don't, but their availability is no gain at all, because you would have exactly the same if you removed property, just the concept of a property is screwed. If you want property qualified ref returning functions, then you also want UFCS properties, and my point is that there is no point to it.My thinking on the other hand is, that properties are the method of encapsulation, so they should ensure it. If something does not, it is not a property, which leads to a very clean design of properties.Such a design is entirely possible today, even if ref properties exist, even if *properties* didn't exist. Why must you use ref properties just because they are available?Note that the reader/user of code is never guaranteed that they are working with properly encapsulated code. A property looks like a field, and a field is NOT encapsulated. So any compiler/language guarantees of encapsulation with properties are moot. -SteveMy point is that it is wrong that a property should look like a field, this just causes confusion, because people mix it up and forget about encapsulation. Just stand to the fact that it is no field. If you want a field, use a field or a method returning ref, don't use property. So there will be guaranteed to have a proper encapsulated field, the moment they see property, but what is more important is, that the provider of the code can be sure that he/she got encapsulation right as long as he/she does qualifies something with property.
Feb 10 2013
On 02/10/2013 01:09 PM, Robert wrote:... In my DIP a property is a function and they behave the same, except that prop=5; calls prop(5); if prop is a property. ...Why does this justify a keyword? I think Walter's initial proposal of getting rid of property has more merit than this.
Feb 10 2013
On Sun, 2013-02-10 at 13:40 +0100, Timon Gehr wrote:Why does this justify a keyword? I think Walter's initial proposal of getting rid of property has more merit than this.Read the DIP? It is about encapsulation and making set functions callable with = in order to be compatible with ref returning functions: (Compatible from set function to ref returning function, not the other way round) and for the more expressive syntax: a=something; instead of a(something); and so that tools can easily extract what's a property. (For enabling access from scripting languages for example, like Qt does.) The one reason why we can not drop it, is that = calls the set function on properties. The reason why we should not, is that having such a cool straight forward feature for providing proper no-boilerplate encapsulation seems valuable in an OOP enabled language.
Feb 10 2013
On 02/10/2013 01:53 PM, Robert wrote:On Sun, 2013-02-10 at 13:40 +0100, Timon Gehr wrote:Stop trolling.Why does this justify a keyword? I think Walter's initial proposal of getting rid of property has more merit than this.Read the DIP?It is about encapsulationPerfectly possible without DIP26 and encapsulation can be violated using property as given in DIP26 just as easily as without it.and making set functions callable with = in order to be compatible with ref returning functions: (Compatible from set function to ref returning function, not the other way round)setter(2);and for the more expressive syntax: a=something;That's not more expressive.instead ofYou mean as well as.a(something); and so that tools can easily extract what's a property. (For enabling access from scripting languages for example, like Qt does.)Use UDAs.The one reason why we can not drop it, is that = calls the set function on properties.So does ( ). And both are the case already.The reason why we should not, is that having such a cool straight forward feature for providing proper no-boilerplateBoilerplate can be trivially automated.encapsulation seems valuable in an OOP enabled language.
Feb 10 2013
Agreed, sorry. But by reading some arguments that are posted over and over again, I just get the feeling that people don't even read it, which is kinda frustrating, as it was a lot of work.Read the DIP?Stop trolling.How?! I mean yeah, you can return a pointer to a field, that is correct. But apart from that, which might get forbidden too for properties (I have to think about it first), what do you mean?It is about encapsulationPerfectly possible without DIP26 and encapsulation can be violated using property as given in DIP26 just as easily as without it.Fine with me. What is the problem?and making set functions callable with = in order to be compatible with ref returning functions: (Compatible from set function to ref returning function, not the other way round)setter(2);If you want to state that the property should assume the given value, it is. Arguably not more than setA(something), but well it is a nice syntax and we stay compatible with ref returning functions and with the current implementation.and for the more expressive syntax: a=something;That's not more expressive.Use UDAs.True if this was the only reason.Yeah, which actually is a good thing, because we won't break much code. People have their code written according to the implementation not some specification, so if we keep most currently existing code running and get sane behaviour, I think this is a good thing, but ok there are people who seem to disagree.The one reason why we can not drop it, is that = calls the set function on properties.So does ( ). And both are the case already.Also true, but integrating it into the language makes the property feature complete and well integrated.The reason why we should not, is that having such a cool straight forward feature for providing proper no-boilerplateBoilerplate can be trivially automated.
Feb 10 2013
How?! I mean yeah, you can return a pointer to a field, that is correct. But apart from that, which might get forbidden too for properties (I have to think about it first), what do you mean?I mean of course you can. Always. There are many ways: - alias this - some other function which returns the variable by ref/pointer - make the field public But the property marked functions won't break it.
Feb 10 2013
The reason why we should not, is that having such a cool straight forward feature for providing proper no-boilerplate encapsulation seems valuable in an OOP enabled language.Provided we actually give properties this meaning in D, which is currently not the case.
Feb 10 2013
On Sun, 10 Feb 2013 07:09:52 -0500, Robert <jfanatiker gmx.at> wrote:Ok, at the very first I have to make clear that my DIP is about changing the actual specification, not trying to make the implementation to match the specification, because in my view of things, the specification is the problem. Properties in my proposal are no longer about optional parentheses ore forbidden parentheses. Properties are a concept hat benefits from the fact, that parentheses are optional, but would work either way.We don't need a feature to implement encapsulation, it's quite possible without property specification. And your proposal does not guarantee encapsulation anyway.Then why do we need special syntax? I don't see the point. This is just back to D1 properties.In the grand scheme of things, the fact that a range's front accessor is a property or a function is not technically important. But front being a property IS important for specific uses. You can't have it so that front is a function only when using it as a range, and a property when using it as a delegate getter.In my DIP a property is a function and they behave the same, except that prop=5; calls prop(5); if prop is a property.And who says what good design is? What if good design means low performance? What if performance is more important? How can you say you know the goals of every possible implementable object and whether encapsulation is entirely necessary for it? You are holding hostage a syntax feature on the concession that it play nice with your "requiring function call" rules. I don't think D should be dictating everything about how you write your properties and methods. This is a systems language, not a nanny language.I think this has to be fixed, because it solves all ambiguities and encourages good design.beIn fact, the only case where a properly-implemented property wouldifrequired on a getter is for delegate properties. I would argue thatrequireproperty worked correctly, it would be possible and correct toDespiter.front to be a property in that template.I don't understand, what is the exact problem with: r.front()()?not matching the specification regarding no parentheses forproperties? The problem is, isInputRange does not require that it is a function, but you ARE requiring that by specifying arbitrary rules.I think you miss the point then. You can't dismiss arguments because they don't fit your narrative. This is a corner case, and not a far-fetched one.Imagine an infinite range (one which never ends), that returns exactly a specific delegate. Such a range could be implemented: struct infiniteDelegate { int delegate() front; enum empty = false; void popFront() {}; }It would, based on the current definition, yes. But what is it good for?Why not simply write: struct infiniteDelegate { int delegate() front(); bool empty() property { return false; } void popFront() {}; }Because then I have to do: id.front()(); To call the delegate. Not what I wanted to design. You are calling into question my design because it doesn't suit your DIP. Why is your DIP more important than my design?You are right, I did not look it up.Actually, that is not true. Check out the definition of hasAssignableElements: By your requirements, hasAssignableElements!(T[]) would necessarily always be false, since UFCS properties are banned, so array.front is not a property. You are saying, I can't assign to the front element of an array. That doesn't sit well with the rest of array's API.Not true, the current definition of front for arrays is: property ref T front(T)(T[] a);which would still work just the same, if you removed property.Right, the setter is not the reason we need property on this, it's the getter. And only for delegate arrays. I should not have brought this example as a reason for UFCS setter properties.Strings are interesting as front returns a non ref dchar (obviously), but they have no writable front anyway. If you would really have a use case where you need an actual setter/getter for an array for example, just do proper encapsulation in a struct/class. If you don't do that, your setter could be bypassed anyway so the design is questionable at best. (Which you could still achieve via alias this, if you really wanted that.)Right, strings are an exception, because they are not treated like arrays. A setter for front would be incorrect for strings.I don't know what this example is trying to prove. I don't see any properties here.Note also that you can have struct-qualified properties (at least you should be able to, it seems Andrei's DIP does not allow it, but it's not at odds with UFCS). Those are just about equivalent to module-level properties, they just require specifying the struct name (and people have used this in clever ways to achieve good readable results).Hmm, no real difference to struct/class properties: import std.stdio; int i; void main() { int i; i=8; writeln(".i: ", .i); writeln(".i: ", testglobal.i); } Prints 0 both times. (The file was named testglobal.d)If it's not a property, it does not behave like a field. If it is a function, then it can behave like a field for all cases except for the delegate case.A ref property pretty much behaves EXACTLY like a field.Exactly that is why I don't consider it a property. :-)Your design dictates that if you want field-like syntax, you have to agree to arbitrary rules regarding ref, and you can't do it with UFCS. Such rules are pretty much arbitrary, because there is no hidden meaning to a property, they are just functions. The only benefit is the readability and the 'human' meaning. Because instead of calling my function setX, I can just call it x, and you have to use the x = ... to call it. But you want to assign some guarantees that really aren't guarantees, they are conventions. In the end, they just get in the way, and your requirements can't achieve the type of guarantees you want.It is not dictated, it is just encouraged and possible. If you don't need encapsulation, don't call it a property. Nothing changes. You even have a way out, if you first considered it a property with proper set/get and later on you decide that this is not really needed, you can drop it, no code will break, you just can not go back. But that was your decision the moment you gave up property.The current thinking instead seems to be that properties are just syntactic sugar and the level of encapsulation is business that isleftto the developer.I don't think that SHOULD be D's business. Encapsulation should be possible, encouraged, but not dictated.Your concept of property is that they are just functions. But we already HAVE functions. There is no reason to have a language feature that says "this is a property" unless it dictates the *syntax*. It is up to the designer of the type to decide how it's parts are called, it should not be up to the caller. Leaving it up to the caller results in unnecessary obfuscation, and hidden meanings where none was intended. There is actually no real need for properties, they are functions, they can be called like functions. We can get along just fine if we have to write: setFoo(x); instead of foo = x; If there is any reason to have a property language feature, it's for syntax, not for design.You don't, but their availability is no gain at all, because you would have exactly the same if you removed property, just the concept of a property is screwed. If you want property qualified ref returning functions, then you also want UFCS properties, and my point is that there is no point to it.My thinking on the other hand is, that properties are the method of encapsulation, so they should ensure it. If something does not, it is not a property, which leads to a very clean design of properties.Such a design is entirely possible today, even if ref properties exist, even if *properties* didn't exist. Why must you use ref properties just because they are available?But they don't see property: auto x = obj.y; // no property in sight. "guarantees" of encapsulation are easily thwarted: struct NotEncapsulated { int x; property int y() { return x;} } -SteveNote that the reader/user of code is never guaranteed that they are working with properly encapsulated code. A property looks like a field, and a field is NOT encapsulated. So any compiler/language guarantees of encapsulation with properties are moot.My point is that it is wrong that a property should look like a field, this just causes confusion, because people mix it up and forget about encapsulation. Just stand to the fact that it is no field. If you want a field, use a field or a method returning ref, don't use property. So there will be guaranteed to have a proper encapsulated field, the moment they see property, but what is more important is, that the provider of the code can be sure that he/she got encapsulation right as long as he/she does qualifies something with property.
Feb 10 2013
On Sun, 2013-02-10 at 10:43 -0500, Steven Schveighoffer wrote:On Sun, 10 Feb 2013 07:09:52 -0500, Robert <jfanatiker gmx.at> wrote:We don't need it. -> Yes. Would it be nice to have. -> Discuss-able. Does it solve the issues we have. -> Yes. Properties as such do guarantee encapsulation, if you access the fields through the property methods. There is no way to forbid the programmer to break it by other members, alias this, or what ever. But as you said D is a systems programming language.Ok, at the very first I have to make clear that my DIP is about changing the actual specification, not trying to make the implementation to match the specification, because in my view of things, the specification is the problem. Properties in my proposal are no longer about optional parentheses ore forbidden parentheses. Properties are a concept hat benefits from the fact, that parentheses are optional, but would work either way.We don't need a feature to implement encapsulation, it's quite possible without property specification. And your proposal does not guarantee encapsulation anyway.Then why do we need special syntax? I don't see the point. This is just back to D1 properties.Actually only two hard requirements: 1. Downwards-Compatibility with functions returning ref. (Downwards means that you can replace a property with a function returning ref, but not the other way round) 2. Backwards compatibility. Not mandatory: 3. Nice syntax Why do we need properties to be radically different than functions? This breaks templates, except we try to make almost everything a property, what DIP23 seems to do. All I do is strive for a clean concept what a property actually is, instead of making everything a property just so that templates work, but by giving up any meaning property could have.And who says what good design is? What if good design means low performance? What if performance is more important? How can you say you know the goals of every possible implementable object and whether encapsulation is entirely necessary for it? You are holding hostage a syntax feature on the concession that it play nice with your "requiring function call" rules.I believe the principles of OOP are very well established and accepted. And once again, you don't have to use properties if they don't match your requirements. Also performance does not suffer from a trivial get/set functions. (For classes make them final if needed)I don't think D should be dictating everything about how you write your properties and methods. This is a systems language, not a nanny language.It does not dictate anything. You do accept that you can not do floating point arithmetic with an integer? What's the difference with properties? If the tool does not fit your need, don't use it.Because then I have to do: id.front()(); To call the delegate. Not what I wanted to design. You are calling into question my design because it doesn't suit your DIP. Why is your DIP more important than my design?You are questioning my DIP, because it does not match your design. How is that better? Seriously this is just my point of view, you can agree or not, all I am trying is to make sure that you understand why I think it is good and to find possible flaws in it, by discussing it. It establishes some semantics for properties, instead of simply making basically everything a property, just so that templates work somehow. The DIP increases uniformity among language features, instead of decreasing it. Also I am obviously convinced that my DIP is a good solution, otherwise I would not have proposed it.Not if we simply accept: front()(); as the syntax to go. It might not look as beautiful as front(), so if you think the syntax for this corner case is just so utterly ugly that it has to be fixed, well then my proposal is rubbish.which would still work just the same, if you removed property.Right, the setter is not the reason we need property on this, it's the getter. And only for delegate arrays. I should not have brought this example as a reason for UFCS setter properties.import std.stdio;Hmm, maybe I misunderstood your argument against module level properties. (The example works the same if i was a property) So what did you mean by: So the point is, a global property could possibly be obscured if you declared a local variable with the same name.int i; void main() { int i; i=8; writeln(".i: ", .i); writeln(".i: ", testglobal.i); } Prints 0 both times. (The file was named testglobal.d)I don't know what this example is trying to prove. I don't see any properties here.right, so its behaviour is uniform with properties.If it's not a property, it does not behave like a field. If it is a function, then it can behave like a field for all cases except for the delegate case.A ref property pretty much behaves EXACTLY like a field.Exactly that is why I don't consider it a property. :-)Your design dictates that if you want field-like syntax, you have to agree to arbitrary rules regarding ref, and you can't do it with UFCS. Such rules are pretty much arbitrary, because there is no hidden meaning to a property, they are just functions. The only benefit is the readability and the 'human' meaning. Because instead of calling my function setX, I can just call it x, and you have to use the x = ... to call it.The most important thing the DIP does, is giving "property" an actual meaning. Also readability is a valid goal, otherwise we could all code in machine code.But you want to assign some guarantees that really aren't guarantees, they are conventions. In the end, they just get in the way, and your requirements can't achieve the type of guarantees you want.So you basically say that OOP does not work? (No offense here, but it is hard to understand for me to understand this statement in any other way)Your concept of property is that they are just functions. But we already HAVE functions. There is no reason to have a language feature that says "this is a property" unless it dictates the *syntax*. It is up to the designer of the type to decide how it's parts are called, it should not be up to the caller. Leaving it up to the caller results in unnecessary obfuscation, and hidden meanings where none was intended. There is actually no real need for properties, they are functions, they can be called like functions. We can get along just fine if we have to write: setFoo(x); instead of foo = x;Agreed, if we started from scratch and did not want this syntactic sugar. The problem is we do not start from scratch and we would basically break every single D program out there.If there is any reason to have a property language feature, it's for syntax, not for design.At the moment. And I am criticizing this very fact. But if you consider this a good thing, than I understand your position completely. Because this way you don't need a meaning of property, you just adopt the rules, until templates work.ref, don't use property.Sure, but how important is this for the caller? The provider of the API has to ensure compatibility. (Also the caller sees it, if she looked at the documentation.)So there will be guaranteed to have a proper encapsulated field, the moment they see property, but what is more important is, that the provider of the code can be sure that he/she got encapsulation right as long as he/she does qualifies something with property.But they don't see property: auto x = obj.y; // no property in sight."guarantees" of encapsulation are easily thwarted: struct NotEncapsulated { int x; property int y() { return x;} }Well no language feature in as systems programming language can prevent you from stupidity. But then, why not get rid of private too, as this is also possible: struct { private int i; public int* u=&i; }
Feb 10 2013
On Sun, 10 Feb 2013 11:52:47 -0500, Robert <jfanatiker gmx.at> wrote:On Sun, 2013-02-10 at 10:43 -0500, Steven Schveighoffer wrote:It does not. property as you have designed it does not "solve" any issues. It does not enforce or guarantee encapsulation. Only the author can do that. One thing I have learned from D's design philosophies is that a guarantee is not a guarantee unless the compiler guarantees it. Like const. Walter constantly derides C++ const as convention, not enforced. This would be the same thing, if someone uses property, then you assume they have encapsulated. Unless they haven't, in which case, the compiler still happily compiles, and your guarantee is gone. How is your DIP any different from a statement that non-ref returning properties guarantee encapsulation? Answer: it's no different. And neither statement is true.On Sun, 10 Feb 2013 07:09:52 -0500, Robert <jfanatiker gmx.at> wrote:We don't need it. -> Yes. Would it be nice to have. -> Discuss-able. Does it solve the issues we have. -> Yes. Properties as such do guarantee encapsulation, if you access the fields through the property methods. There is no way to forbid the programmer to break it by other members, alias this, or what ever. But as you said D is a systems programming language.Ok, at the very first I have to make clear that my DIP is aboutchangingthe actual specification, not trying to make the implementation tomatchthe specification, because in my view of things, the specification is the problem. Properties in my proposal are no longer about optional parentheses ore forbidden parentheses. Properties are a concept hat benefits from the fact, that parentheses are optional, but would work either way.We don't need a feature to implement encapsulation, it's quite possible without property specification. And your proposal does not guarantee encapsulation anyway.Why do we need properties to be radically different than functions? This breaks templates, except we try to make almost everything a property, what DIP23 seems to do. All I do is strive for a clean concept what a property actually is, instead of making everything a property just so that templates work, but by giving up any meaning property could have.They aren't *radically* different from functions, the syntax is different. Under the hood, they are identical to functions. Well, a certain form of functions.It is true that properties are mostly in OOP languages. But D is not strictly OOP. structs are not OOP, and you can have properties on them. Static properties can exist, and they have absolutely nothing to do with OOP. It is a syntax modification. Encapsulation, an OOP design, does not require a special property syntax to implement them.And who says what good design is? What if good design means low performance? What if performance is more important? How can you say you know the goals of every possible implementable object and whether encapsulation is entirely necessary for it? You are holding hostage a syntax feature on the concession that it play nice with your "requiring function call" rules.I believe the principles of OOP are very well established and accepted. And once again, you don't have to use properties if they don't match your requirements. Also performance does not suffer from a trivial get/set functions. (For classes make them final if needed)Actually, floating point is 2 integers. And yes, you can do floating point math with integers. I do it all the time to avoid the issues with floating point. But beside that point, your properties bring nothing to the table, so I can actually do without them completely. They are a tool that fixes problems that are already fixed.I don't think D should be dictating everything about how you write your properties and methods. This is a systems language, not a nanny language.It does not dictate anything. You do accept that you can not do floating point arithmetic with an integer? What's the difference with properties? If the tool does not fit your need, don't use it.The issue is, my design is limited to MY library, your DIP affects EVERY library (or would if implemented). The bar is much higher that you have to pass, since everyone will have to play by your rules. Without your DIP, I can have my library, and others can have their libraries which might require you to use id.front()(). Freedom of design is definitely not something to take away lightly.Because then I have to do: id.front()(); To call the delegate. Not what I wanted to design. You are calling into question my design because it doesn't suit your DIP. Why is your DIP more important than my design?You are questioning my DIP, because it does not match your design. How is that better? Seriously this is just my point of view, you can agree or not, all I am trying is to make sure that you understand why I think it is good and to find possible flaws in it, by discussing it.It establishes some semantics for properties, instead of simply making basically everything a property, just so that templates work somehow. The DIP increases uniformity among language features, instead of decreasing it. Also I am obviously convinced that my DIP is a good solution, otherwise I would not have proposed it.All the property proposals establish semantics for properties. Nobody is making everything a property, save perhaps your DIP, which mostly equates functions and properties, so I don't really get that. Your dip makes things much less uniform IMO, since properties should syntactically be more like fields than functions. With your DIP, I am forced to require "property or function" in a template, I can't require "field or property". Seeing as how properties are actually functions, I don't see the point. I feel this takes the major draw of properties away.It's not about the beauty. A field that is a delegate does not require two sets of parentheses. In this case, properties would behave like functions, and we already HAVE functions that execute arbitrary code, we don't need another language construct that executes arbitrary code and is called exactly like a function. So in your DIP, properties are pretty much redundant.Not if we simply accept: front()(); as the syntax to go. It might not look as beautiful as front(), so if you think the syntax for this corner case is just so utterly ugly that it has to be fixed, well then my proposal is rubbish.which would still work just the same, if you removed property.Right, the setter is not the reason we need property on this, it's the getter. And only for delegate arrays. I should not have brought this example as a reason for UFCS setter properties.The original text this was in reply to made this confusing. What I was saying is that struct static fields/properties do not interfere with UFCS, and are as global as global fields/properties.import std.stdio;Hmm, maybe I misunderstood your argument against module level properties. (The example works the same if i was a property) So what did you mean by: So the point is, a global property could possibly be obscured if you declared a local variable with the same name.int i; void main() { int i; i=8; writeln(".i: ", .i); writeln(".i: ", testglobal.i); } Prints 0 both times. (The file was named testglobal.d)I don't know what this example is trying to prove. I don't see any properties here.Again, we have fields, we have functions. If you want to make a *new type* of function, it needs to justify its existence. I don't see anything compelling for properties as you see them, they act just like functions.right, so its behaviour is uniform with properties.If it's not a property, it does not behave like a field. If it is a function, then it can behave like a field for all cases except for the delegate case.A ref property pretty much behaves EXACTLY like a field.Exactly that is why I don't consider it a property. :-)Right, a meaning that is not true.Your design dictates that if you want field-like syntax, you have to agree to arbitrary rules regarding ref, and you can't do it with UFCS. Such rules are pretty much arbitrary, because there is no hidden meaning to a property, they are just functions. The only benefit is the readability and the 'human' meaning. Because instead of calling my function setX, I can just call it x, and you have to use the x = ... to call it.The most important thing the DIP does, is giving "property" an actual meaning. Also readability is a valid goal, otherwise we could all code in machine code.No, I have no idea how you get that. Whether or not you *can* encapsulate with properties is a different statement than whether properties *guarantee* encapsulation. What you have is something that is unnecessarily strict, in exchange for a false guarantee. That's all I said. It had nothing to do with whether encapsulation is good practice, or if OOP works.But you want to assign some guarantees that really aren't guarantees, they are conventions. In the end, they just get in the way, and your requirements can't achieve the type of guarantees you want.So you basically say that OOP does not work? (No offense here, but it is hard to understand for me to understand this statement in any other way)Well, we actually are starting from pretty much what you are proposing. Your proposal adds complexity for no gain.Your concept of property is that they are just functions. But we already HAVE functions. There is no reason to have a language feature that says "this is a property" unless it dictates the *syntax*. It is up to the designer of the type to decide how it's parts are called, it should not be up to the caller. Leaving it up to the caller results in unnecessary obfuscation, and hidden meanings where none was intended. There is actually no real need for properties, they are functions, they can be called like functions. We can get along just fine if we have to write: setFoo(x); instead of foo = x;Agreed, if we started from scratch and did not want this syntactic sugar. The problem is we do not start from scratch and we would basically break every single D program out there.Your counter proposal is to make property essentially a no-op. If you want to criticize, that is fine. If you want to establish a convention that using property to encapsulate really requires not returning ref, or using them with UFCS (which is in fact incorrect), that is fine too. But in order to have a reason to have property stay in the language, it has to be a feature that isn't easily done otherwise. It needs to pull it's weight. Having it just be another function isn't worth it.If there is any reason to have a property language feature, it's for syntax, not for design.At the moment. And I am criticizing this very fact. But if you consider this a good thing, than I understand your position completely. Because this way you don't need a meaning of property, you just adopt the rules, until templates work.I don't think it is important. That is why your whole DIP is needless. As an object author, I can easily ensure encapsulation whether properties are used or not. properties as you define them give me no extra bonuses or features, they are simply functions. If your DIP is implemented, and any programmer looks at a property method and says "aha! that field is entirely encapsulated because it has property on it," I would call that programmer foolish. Any guarantees that you have to double check yourself are not guarantees.ref, don't use property.Sure, but how important is this for the caller? The provider of the API has to ensure compatibility. (Also the caller sees it, if she looked at the documentation.)So there will be guaranteed to have a proper encapsulated field, the moment they see property, but what is more important is, that the provider of the code can be sure that he/she got encapsulation rightaslong as he/she does qualifies something with property.But they don't see property: auto x = obj.y; // no property in sight.Again, when you say "guarantees", that is a strong term. If property claims to guarantee encapsulation, it better ensure the above doesn't compile, because otherwise it's not guaranteed. The rule in D is that if it guarantees something, the only way to get around it is to cast. This way, you can use cast as a red flag to indicate some guarantee may be broken. private does not guarantee that others cannot access it through other references. It simply is a tool with which you CAN guarantee others cannot access it. properties are no different, they do not guarantee encapsulation, with or without your DIP, they only provide a mechanism to be able to provide that guarantee. -Steve"guarantees" of encapsulation are easily thwarted: struct NotEncapsulated { int x; property int y() { return x;} }Well no language feature in as systems programming language can prevent you from stupidity. But then, why not get rid of private too, as this is also possible: struct { private int i; public int* u=&i; }
Feb 10 2013
On 2/8/13 2:05 PM, Robert wrote:Look at the section "No module-level properties". Why not?! That's a perfectly valid use of properties. The proposal disallows module-level properties, but instead allows: 42.fun = 43; which reads like: assign 43 to the fun property of 42. We get this really obscure feature but disallowing module-level properties? If that is not wrong, than I don't know what is.There would be ambiguities with module level properties. A property with one argument may be either a setter for a module-level property or a getter for the property of a module-level object. Andrei
Feb 08 2013
On Friday, 8 February 2013 at 21:02:10 UTC, Andrei Alexandrescu wrote:On 2/8/13 2:05 PM, Robert wrote:I think this was settled, allowing such property to only be a getter via UFCS.Look at the section "No module-level properties". Why not?! That's a perfectly valid use of properties. The proposal disallows module-level properties, but instead allows: 42.fun = 43; which reads like: assign 43 to the fun property of 42. We get this really obscure feature but disallowing module-level properties? If that is not wrong, than I don't know what is.There would be ambiguities with module level properties. A property with one argument may be either a setter for a module-level property or a getter for the property of a module-level object.
Feb 08 2013
On Thursday, 7 February 2013 at 16:33:46 UTC, Andrei Alexandrescu wrote:On 2/7/13 9:44 AM, eles wrote:At least it caught a bit of attention... but I agree. Sorry.On Wednesday, 6 February 2013 at 22:10:29 UTC, Robert wrote:I think the sarcasm is uncalled for. We're doing our best here and our intent is indeed to have properties emulate fields.Properties emulate fields, but they can't behave 100% like fields because if they did they'd be fields.That's no reason to make them functions instead. Or something so far from fields that becomes cumbersome. The basic idea is: "properties are (a little more) that fields with validation and directional access control". That's all. Notice that in the brackets above there is "more", but also it is prefixed by "a little".
Feb 07 2013