digitalmars.D - Possible property compromise
- Steven Schveighoffer (53/53) Jan 29 2013 @property has gotten a lot of flak lately, and I think the unenthusiasti...
- q66 (6/64) Jan 29 2013 no, just no.
- Adam D. Ruppe (11/11) Jan 29 2013 Not awful... but what about opDispatch setters?
- Timon Gehr (4/9) Jan 29 2013 private int _s;
- Adam D. Ruppe (2/4) Jan 29 2013 ah yes, outstanding. So that's workable.
- FG (2/9) Jan 29 2013 It's inconceivable why on earth would you call this a "compromise". :)
- Jonathan M Davis (23/24) Jan 29 2013 It seems like it could work, but without a way to explictly make somethi...
- Rob T (18/24) Jan 29 2013 On Tuesday, 29 January 2013 at 23:09:55 UTC, Jonathan M Davis
- Jonathan M Davis (13/42) Jan 29 2013 I believe that two main things are needed:
- q66 (2/2) Jan 29 2013 It deeply disturbs me that people even take the original post
- q66 (6/8) Jan 29 2013 That said, obviously, propreties should be implemented in the
- deadalnix (3/5) Jan 29 2013 Well, you may give some arguments instead of no, just no, to
- q66 (4/9) Jan 30 2013 It just gives another meaning to foo.bar, and ENFORCING camelCase
- Steven Schveighoffer (3/13) Jan 30 2013 Apparently not the designers of objective-C.
- q66 (3/19) Jan 31 2013 Not contradictory, Objective-C is not a well designed language :)
- Steven Schveighoffer (10/29) Jan 31 2013 Now we're just name calling ;) I tend to think that for the most
- jerro (6/9) Jan 31 2013 This is a really bad argument. The facts that language is being
- Regan Heath (8/16) Jan 31 2013 Small point. "using" != "standadized on". The latter implies some
- SomeDude (4/20) Feb 02 2013 I bet the reason why Objective-C was chosen rather than C++ has
- Steven Schveighoffer (10/16) Jan 31 2013 From what I remember Andrei saying, they write their code in C++ and
- Jacob Carlborg (7/9) Jan 31 2013 I'm pretty sure it's the opposite. PHP code compiles to C++.
- Andrei Alexandrescu (5/12) Jan 31 2013 We use JITting right now:
- Andrei Alexandrescu (2/3) Jan 31 2013 s/that/on that/
- Jacob Carlborg (4/6) Jan 31 2013 Aha, I didn't know that.
- Timon Gehr (2/8) Jan 31 2013 Other way round!
- q66 (6/43) Jan 31 2013 No, that is not a solution either. Any of these setBlah or
- Steven Schveighoffer (14/25) Jan 31 2013 I don't agree, the benefit of being able to refer to the property as a
- Jacob Carlborg (9/14) Jan 31 2013 And that is thanks to Clang and LLVM. Xcode wouldn't be nearly as good
- Steven Schveighoffer (8/9) Jan 30 2013 Sorry it offends you, but maybe you could have a constructive comment
- Rob T (30/50) Jan 29 2013 I agree partial emulation can work, and I see you've pointed out
- H. S. Teoh (21/27) Jan 29 2013 [...]
- Zach the Mystic (5/29) Jan 29 2013 outer.this
- Zach the Mystic (5/17) Jan 29 2013 Actually, you're right. I see no overloading of the address
- Jonathan M Davis (14/16) Jan 29 2013 In order to restrict what you can do with it to the subset of operations...
- H. S. Teoh (10/28) Jan 29 2013 [...]
- Adam Wilson (10/36) Jan 29 2013 Indeed, but a better idea would be to fix it, throwing it out seems a bi...
- H. S. Teoh (11/48) Jan 29 2013 [...]
- Chad Joan (22/28) Jan 29 2013 I hate to be a bringer of bad news, but I don't think getter/setter
- H. S. Teoh (21/54) Jan 29 2013 This is easy to fix in the compiler.
- Jonathan M Davis (10/16) Jan 29 2013 But the type would be different. You wouldn't be able to do stuff like
- TommiT (8/15) Jan 29 2013 I always thought that having public member variables is a bad
- H. S. Teoh (14/31) Jan 29 2013 Property functions are precisely what gives you encapsulation.
- Adam Wilson (11/26) Jan 29 2013 Not really, public fields ARE bad, but properties allow you to sanitize ...
- Rob T (31/47) Jan 29 2013 Well, the main reason why this was bad convention, is because the
- TommiT (11/26) Jan 30 2013 Somehow I had missed this post. So, we can bury the idea of
- TommiT (6/10) Jan 30 2013 And frankly, I think it's a good thing. Because this way we can
- TommiT (11/15) Jan 30 2013 The moral of the story:
- Jacob Carlborg (4/19) Jan 30 2013 That would require some property rewrite by the compiler.
- Jonathan M Davis (56/74) Jan 29 2013 Aside from the ability to take the variable's address, what really is th...
- TommiT (7/86) Jan 29 2013 Okay, I can see how that could work. But I still stand
- Chad Joan (11/26) Jan 29 2013 No, it means that style of programming is no longer bad.
- deadalnix (7/23) Jan 29 2013 Belief is rarely a good thing.
- TommiT (4/6) Jan 29 2013 I don't agree. I think public variables are an encapsulation
- deadalnix (2/8) Jan 29 2013 Sounds like religious reasoning.
- TommiT (9/13) Jan 29 2013 I don't understand you. According to wikipedia, encapsulation is:
- Adam D. Ruppe (5/5) Jan 29 2013 There's times when a member variable manages its own invariant
- Andrei Alexandrescu (4/19) Jan 29 2013 The thing here is that properties offer control over changing the
- Jacob Carlborg (5/11) Jan 30 2013 I really don't see much point in properties/methods that just forwards
- Andrei Alexandrescu (3/12) Jan 30 2013 Insurance.
- TommiT (20/22) Jan 30 2013 I assume you mean something like this:
- Jacob Carlborg (6/24) Jan 30 2013 Sure, but I think that's what properties are for. We currently don't
- 1100110 (6/15) Jan 30 2013 Me either.
- TommiT (4/10) Jan 30 2013 Putting in public variables sounds like not thinking, to me.
- Jonathan M Davis (12/31) Jan 30 2013 The main reason for it is that you can add additional code later when it...
- Era Scarecrow (44/47) Jan 30 2013 If we didn't have to interface with C and we were willing to get
- Jacob Carlborg (15/28) Jan 30 2013 Implement this:
- Steven Schveighoffer (20/30) Jan 30 2013 I don't think this is quite right.
- H. S. Teoh (22/56) Jan 30 2013 [...]
- Jonathan M Davis (13/17) Jan 29 2013 It works if you can restrict a variable to a reasonable subset of its no...
- TommiT (17/23) Jan 29 2013 I had a thought. What if we use this opportunity to also fix the
- Timon Gehr (2/3) Jan 30 2013 Nope.
- Jonathan M Davis (5/9) Jan 30 2013 It was my understanding that it did. Everything that I've read on it ind...
- Timon Gehr (3/12) Jan 30 2013 (C# has ref parameters. Properties cannot be passed by ref, but public
- Jacob Carlborg (4/7) Jan 30 2013 Last time I used C# it didn't have property rewrite when returning struc...
- Jesse Phillips (38/38) Jan 29 2013 Sorry I have to oppose this. It is in no way a compromise as it
- Jonathan M Davis (3/5) Jan 29 2013 The prime example of that would be save.
- deadalnix (3/9) Jan 29 2013 rehash, dup, length (as a setter), the list goes on and on.
- deadalnix (12/17) Jan 29 2013 Yes, this is true, like always. Even when property isn't involved.
- H. S. Teoh (13/33) Jan 29 2013 +1. Too many C programmers (including myself) have preconceived notions
- Rob T (5/24) Jan 29 2013 Yes, very good points. We're likely optimizing away for little to
- Steven Schveighoffer (35/69) Jan 30 2013 You are welcome to it! I don't know if there is a thread on this
- Zach the Mystic (15/18) Jan 30 2013 It's only natural that a person wants to advocate for his or her
- Steven Schveighoffer (10/25) Jan 31 2013 What you describe is almost exactly something I suggested when the
- Michel Fortin (24/26) Jan 31 2013 I haven't participated in the discussions about properties this time
- Steven Schveighoffer (44/59) Jan 31 2013 Yes, I saw your post when looking for my post about the C# style which I...
- Michel Fortin (21/42) Jan 31 2013 Could also have used global functions instead of static ones inside of
- Zach the Mystic (13/21) Jan 31 2013 I'm hoping that the community won't close the books on this issue
- Zach the Mystic (19/19) Jan 31 2013 On Thursday, 31 January 2013 at 19:13:03 UTC, Zach the Mystic
- Steven Schveighoffer (11/22) Jan 31 2013 I looked at it, it seems extremely similar to C# properties, which has
- Zach the Mystic (26/39) Jan 31 2013 Thanks for looking at it.
- Steven Schveighoffer (35/53) Jan 31 2013 C# has properties like this:
- Steven Schveighoffer (7/9) Jan 31 2013 Forgot to finish this sentence before I hit send.
- Era Scarecrow (3/12) Jan 31 2013 Except when postblit is defined...? Or opAssign?
- Steven Schveighoffer (5/19) Jan 31 2013 I'm pretty sure structs are forbidden to have internal pointers. They
- Era Scarecrow (7/25) Jan 31 2013 Hmmm... Well I threw out an idea about not returning inner
- Jonathan M Davis (5/7) Jan 31 2013 Structs must be moveable. I believe that you can technically have a stru...
- Zach the Mystic (58/108) Jan 31 2013 I think my suggestion goes far beyond what you suspect. It goes
- TommiT (5/6) Jan 31 2013 No it won't. It will print "n()".
- TommiT (28/38) Jan 31 2013 And here's another example of why it is as big of a problem as I
- TommiT (2/3) Jan 31 2013 ...make it out to be...
- Zach the Mystic (6/32) Jan 31 2013 I'm sorry, I know very little about race conditions. If you might
- TommiT (13/50) Jan 31 2013 spawn(&func!int, arr.length);
- Zach the Mystic (8/60) Jan 31 2013 I'm familiar with the fact that programmers face endless woes
- TommiT (49/113) Feb 01 2013 Actually, that example of mine was wrong - it's not a data-race.
- Zach the Mystic (5/12) Jan 31 2013 I need to study this principle a little more. In other words,
- TommiT (5/9) Jan 31 2013 No, alias this is basically implicit cast operator that will be
- Zach the Mystic (6/16) Jan 31 2013 If what you say is true, then all the more reason to build opGet
- Zach the Mystic (12/19) Jan 31 2013 to!string(foo.n)... hmmm... not that I know how to solve it right
- Zach the Mystic (11/23) Jan 31 2013 I think this is taken care of actually, with opCast(string). The
- TommiT (5/8) Jan 31 2013 Yes, there's probably a way to pass to writeln by providing
- Zach the Mystic (6/15) Jan 31 2013 Not really sure what you mean. I have a bunch of thoughts, but my
- TommiT (8/14) Jan 31 2013 None of the alias this conversions are even looked at when you
- Zach the Mystic (3/21) Jan 31 2013 What I meant to suggest was an actual new feature which would
- Zach the Mystic (4/26) Jan 31 2013 Frankly, it was your use of the word "insurmountable" which
- Steven Schveighoffer (16/60) Jan 31 2013 No, the struct must have data. If it doesn't, how does it get back to t...
- Zach the Mystic (73/105) Jan 31 2013 How does any function get hooked up with data? The compiler
- Zach the Mystic (18/32) Feb 01 2013 What I mean is, that the annoying aspect of making struct-nested
- Steven Schveighoffer (114/180) Feb 01 2013 No need to get snippy :) Especially when you are wrong.
- Zach the Mystic (19/224) Feb 01 2013 Okay, so you're drawing the line where you think it ends.
- Michel Fortin (17/23) Feb 01 2013 I think what Steven is saying is that you're distorting the concept of
- Zach the Mystic (32/52) Feb 01 2013 Yes, this is exactly what I am trying to do, because it's yet
- Steven Schveighoffer (21/64) Feb 01 2013 I think you are wrong in how you assume a struct works, but not in your ...
- Zach the Mystic (11/33) Feb 01 2013 I disagree. It is absolutely the fundamental key to this formula.
- Steven Schveighoffer (34/48) Feb 01 2013 Well, we can disagree, but you still haven't explained why it's
- Zach the Mystic (27/79) Feb 01 2013 Okay, fair.
- Timon Gehr (7/14) Feb 01 2013 The modifier actually has a consistent meaning.
- Zach the Mystic (3/8) Feb 04 2013 Do you mind if I put my arguments in a new thread?
- Rob T (13/24) Feb 04 2013 FYI, I got some feedback from Andrei today in the DIP23 thread ...
- Rob T (35/35) Feb 01 2013 I've had to step away from this for a while, but I want to say
- Zach the Mystic (21/58) Feb 01 2013 I don't like this because structs don't already work that way.
- Rob T (53/95) Feb 01 2013 It's one thing to implement a struct, and another thing to
- Zach the Mystic (15/21) Feb 01 2013 I am not proposing this and I don't think it's actually
- Zach the Mystic (30/51) Feb 01 2013 I mean a code example. But since I'm already here:
- TommiT (29/30) Feb 01 2013 That wouldn't compile, so you must mean:
- Era Scarecrow (10/18) Feb 01 2013 It would refuse to compile as a static function can't point to
- Zach the Mystic (2/6) Feb 02 2013 Does my suggested way of doing it not do this?
- Zach the Mystic (9/28) Feb 02 2013 ... well, this function requires being called with instances of
- Era Scarecrow (25/45) Feb 02 2013 Yes, it should be callable that way since it knows where a is
- Zach the Mystic (18/66) Feb 02 2013 I think this belittles just how important that implementation
- TommiT (8/14) Feb 02 2013 If Tail is an autonomous struct/class, then it totally makes
- Zach the Mystic (4/19) Feb 02 2013 A dog's tail is not an autonomous struct/class. If you ever had a
- Zach the Mystic (5/25) Feb 02 2013 I'm sorry, I'm just getting allergic to the word "namespace",
- Era Scarecrow (35/55) Feb 02 2013 Agreed 100%, Although a second (instance of) Dog may want to
- Zach the Mystic (15/50) Feb 02 2013 There is a bug in this code and it would not compile. Your getId
- Era Scarecrow (16/66) Feb 03 2013 I don't see the bug. Tail is known to be a nested struct so it
- Zach the Mystic (26/56) Feb 02 2013 You're right. I don't know how the compiler stores the name of
- TommiT (10/40) Feb 02 2013 Yes, I can see that now. I didn't understand that the code wasn't
- Zach the Mystic (2/13) Feb 02 2013 I'm sure I'll get by, with a little help from my friends.
- TommiT (14/15) Feb 01 2013 What do you suppose would happen if I wrote the following?
- Zach the Mystic (4/19) Feb 02 2013 With my new rules? It would be illegal to take the address of a
- TommiT (8/30) Feb 02 2013 Yes, that is kind of what I was getting at with my question. But
- Zach the Mystic (2/34) Feb 02 2013 Yes, I believe so. I don't see why not.
- TommiT (7/8) Feb 01 2013 What I'm trying to tell you through those questions is that what
- TommiT (28/29) Feb 01 2013 Then, if we used your proposed nested structs to implement
- Zach the Mystic (20/49) Feb 02 2013 This code is both wrong and has nothing whatever to do with the
- TommiT (14/72) Feb 02 2013 No, you're not getting it. The following is a function template:
- TommiT (34/37) Jan 31 2013 I'm just going to repeat the arguments I've already made on the
- Michel Fortin (14/16) Jan 31 2013 Don't take it personally. I'm not saying anything about your proposal,
- Jesse Phillips (11/14) Jan 31 2013 I don't think the community is ready to close the books on this.
- Zach the Mystic (12/21) Jan 31 2013 Also if you're worried about the code breakage necessary to get
- Michael (6/6) Jan 31 2013 Static nested struct as property... what is going on...
- Jesse Phillips (40/98) Jan 31 2013 Thank you.
- Andrei Alexandrescu (3/5) Jan 31 2013 FWIW we want to keep a means to define properties.
- Jonathan M Davis (10/14) Jan 31 2013 Well, it doesn't even come close. For the most part, the pro-@property f...
- Andrei Alexandrescu (4/17) Jan 31 2013 Under some proposals range.popFrontN = 7 would not compile because
- Steven Schveighoffer (6/31) Jan 31 2013 I don't think this rule is good enough.
- Andrei Alexandrescu (3/34) Jan 31 2013 I agree. Was just sayin'.
- Steven Schveighoffer (50/137) Jan 31 2013 I meant the @property design, including the keyword. Basically whatever...
- Michael (43/44) Feb 02 2013 As proposal:
property has gotten a lot of flak lately, and I think the unenthusiastic implementation of it really hasn't helped. BUT... there are a few problems with the original non- property implementation that are fixed by having additional syntax (well, if it was properly implemented): 1. Treating any old function as a setter. This is the writeln = "hi"; mess 2. Forcing you to use 2 sets of parentheses when returning a callable type. However, we have seen the addition of two problems with property. First is when UFCS was introduced. property int iprop(int val) {...} can be called as: 52.iprop; or iprop = 52; Second problem is, when ref returns are used on properties: property ref int iprop(); auto x = &iprop; Should x be the delegate for iprop, or call iprop and get the address of the return value? ASIDE from the disdain that many developers have towards property, I think above anything else, that the first problem property fixed above is essential to the freedom of naming functions for API designers. The second problem of getting delegates via properties is fixed, so it would be a step backwards if we just removed property. So in light of all that, I propose a compromise: 1. Deprecate property. 2. When the compiler encounters a field setting like this: x.y = ...; If a y field exists on the aggregate represented by x, then that is the assumed member being referenced, and compilation continues normally. If there is no y field, then then the compiler ALSO tries: x.setY(...); It is important to note that: x.y(...); does not compile, y is not just another function. To call in function form, you must call: x.setY(...); That takes care of setters, AND takes care of the new problems with property. 3. Parentheses remain optional on functions, allowing the creation of getters as before property. However, this does not fix the delegate problem. To fix that problem, we can use the complementary getY to allow specifying a getter that does not absorb parentheses. One problem I will note with this scheme, some Unicode symbols that may be valid D symbol starters may NOT have an upper/lower case, making it impossible to use those as properties. But I admit having an English bias so I don't see this as a large problem. Besides, "set" is already English. Note, I've been doing a lot of Objective C lately, and I kind of like the property scheme there (this is quite similar). Sound crazy? Ridiculous? Impossible? Insulting? What do you think? -Steve
Jan 29 2013
On Tuesday, 29 January 2013 at 17:10:00 UTC, Steven Schveighoffer wrote:property has gotten a lot of flak lately, and I think the unenthusiastic implementation of it really hasn't helped. BUT... there are a few problems with the original non- property implementation that are fixed by having additional syntax (well, if it was properly implemented): 1. Treating any old function as a setter. This is the writeln = "hi"; mess 2. Forcing you to use 2 sets of parentheses when returning a callable type. However, we have seen the addition of two problems with property. First is when UFCS was introduced. property int iprop(int val) {...} can be called as: 52.iprop; or iprop = 52; Second problem is, when ref returns are used on properties: property ref int iprop(); auto x = &iprop; Should x be the delegate for iprop, or call iprop and get the address of the return value? ASIDE from the disdain that many developers have towards property, I think above anything else, that the first problem property fixed above is essential to the freedom of naming functions for API designers. The second problem of getting delegates via properties is fixed, so it would be a step backwards if we just removed property. So in light of all that, I propose a compromise: 1. Deprecate property. 2. When the compiler encounters a field setting like this: x.y = ...; If a y field exists on the aggregate represented by x, then that is the assumed member being referenced, and compilation continues normally. If there is no y field, then then the compiler ALSO tries: x.setY(...);no, just no.It is important to note that: x.y(...); does not compile, y is not just another function. To call in function form, you must call: x.setY(...); That takes care of setters, AND takes care of the new problems with property. 3. Parentheses remain optional on functions, allowing the creation of getters as before property. However, this does not fix the delegate problem. To fix that problem, we can use the complementary getY to allow specifying a getter that does not absorb parentheses. One problem I will note with this scheme, some Unicode symbols that may be valid D symbol starters may NOT have an upper/lower case, making it impossible to use those as properties. But I admit having an English bias so I don't see this as a large problem. Besides, "set" is already English."natural language inspiration" ... hmm .. where have I seen this? oh right, let's make a DOBOL.Note, I've been doing a lot of Objective C lately, and I kind of like the property scheme there (this is quite similar). Sound crazy? Ridiculous? Impossible? Insulting? What do you think? -Stevemore like all four combined.
Jan 29 2013
Not awful... but what about opDispatch setters? Perhaps we could do it this way: void opSet(string variable, T)(T value) {} Foo foo; foo.s = 10; // if s doesn't exist, do opSet!"s"(10) If you only want a setter for one particular name void opSet(string name : "s")(int val) {} It'd solve the unicode thing too, though at the cost of a little more verboseness for some things. Oh crap what if it needs to be virtual. Blargh. I'll throw it out anyway.
Jan 29 2013
On 01/29/2013 06:16 PM, Adam D. Ruppe wrote:Not awful... but what about opDispatch setters? Perhaps we could do it this way: void opSet(string variable, T)(T value) {} ... Oh crap what if it needs to be virtual. Blargh. I'll throw it out anyway.private int _s; protected void setS(int value){ this._s=value; } template opSet(string variable : "s")(int value){ alias opSet = setS; }
Jan 29 2013
On Tuesday, 29 January 2013 at 17:21:31 UTC, Timon Gehr wrote:template opSet(string variable : "s")(int value){ alias opSet = setS; }ah yes, outstanding. So that's workable.
Jan 29 2013
On 2013-01-29 18:10, Steven Schveighoffer wrote:If there is no y field, then then the compiler ALSO tries: x.setY(...); [...] One problem I will note with this scheme, some Unicode symbols that may be valid D symbol starters may NOT have an upper/lower case, making it impossible to use those as properties. But I admit having an English bias so I don't see this as a large problem. Besides, "set" is already English.It's inconceivable why on earth would you call this a "compromise". :)
Jan 29 2013
On Tuesday, January 29, 2013 12:10:04 Steven Schveighoffer wrote:Sound crazy? Ridiculous? Impossible? Insulting?It seems like it could work, but without a way to explictly make something a getter property, it will be impossible to change a property function into a variable later without risking breaking code, because then people will still be able to call the property function with parens. Using parens on getter properties has to be illegal for that to work. And if we want it to work to be able to swap a variable for a property function (which is one of the purposes of properties in the first place), not only do we need to improve the property rewriting (which could be done with your scheme), but we'd need to be able to mark a variable in such a way that it couldn't be used for anything which wouldn't work with a property function (e.g. taking its address would have to be illegal), and for that, you'd need an explicit attribute such as property. So, if we want to be able to swap between variables and property functions during refactoring or design changes or whatnot (as properties are supposed to allow), we're going to need explicit properties of some kind. That could be done with getProp and setProp instead of property if we really wanted to, but we'd still need a way to mark variables, and for that, you'd probably need an actual attribute like property. If we go any route other than explicit properties, we're giving up on the possibility of being able to swap variables and property functions without breaking code. - Jonathan M Davis
Jan 29 2013
On Tuesday, 29 January 2013 at 23:09:55 UTC, Jonathan M Davis wrote: [..]If we go any route other than explicit properties, we're giving up on the possibility of being able to swap variables and property functions without breaking code. - Jonathan M DavisGiven how D currently works, I don't see how we can realistically implement a function as a drop in replacement for a variable and expect code to continue working as if nothing had changed. One of the bigger problems is that the getter returns by value, not ref, so everything that expects a ref return will fail. I expect to make precise variable emulation through properties will require a lot of compiler magic, and there will be inevitable bugs and conflicts that follow. I really don't see that there's enough value with the property concept to justify the costs of precise variable emulation. You know a lot more about implementing compiler magic than I do, so I'll ask you if you think the effort is doable enough to justify having property functions that can act like a drop in replacement for existing variables? --rt
Jan 29 2013
On Wednesday, January 30, 2013 00:55:13 Rob T wrote:On Tuesday, 29 January 2013 at 23:09:55 UTC, Jonathan M Davis wrote: [..]I believe that two main things are needed: 1. Make it possible to mark a variable such that you can't do anything with it that you couldn't do with a property function (e.g. taking its address needs to be illegal). 2. Add property rewrites to make it so that stuff like ++ and += work. You'll never get a property function to operate 100% like a variable, but you property functions swappable because it do stuff like let you take the address of a variable or a function. We basically need to do the same by restricting variables which are properties and improving the rewrites that the compile does for property functions. - Jonathan M DavisIf we go any route other than explicit properties, we're giving up on the possibility of being able to swap variables and property functions without breaking code. - Jonathan M DavisGiven how D currently works, I don't see how we can realistically implement a function as a drop in replacement for a variable and expect code to continue working as if nothing had changed. One of the bigger problems is that the getter returns by value, not ref, so everything that expects a ref return will fail. I expect to make precise variable emulation through properties will require a lot of compiler magic, and there will be inevitable bugs and conflicts that follow. I really don't see that there's enough value with the property concept to justify the costs of precise variable emulation. You know a lot more about implementing compiler magic than I do, so I'll ask you if you think the effort is doable enough to justify having property functions that can act like a drop in replacement for existing variables?
Jan 29 2013
It deeply disturbs me that people even take the original post seriously.
Jan 29 2013
On Wednesday, 30 January 2013 at 00:26:11 UTC, q66 wrote:It deeply disturbs me that people even take the original post seriously.That said, obviously, propreties should be implemented in the library using opDot, with std.property implementing several property-handling policies and abstracted away in some kind of OO interface with inheritance to implement custom ones. That's gonna be awesome. Don't you think?
Jan 29 2013
On Wednesday, 30 January 2013 at 00:26:11 UTC, q66 wrote:It deeply disturbs me that people even take the original post seriously.Well, you may give some arguments instead of no, just no, to convince people.
Jan 29 2013
On Wednesday, 30 January 2013 at 03:02:38 UTC, deadalnix wrote:On Wednesday, 30 January 2013 at 00:26:11 UTC, q66 wrote:It just gives another meaning to foo.bar, and ENFORCING camelCase by the language while lowercasing shit is just horrible. Anyone with a slightest trace of language design sense realizes that.It deeply disturbs me that people even take the original post seriously.Well, you may give some arguments instead of no, just no, to convince people.
Jan 30 2013
On Wed, 30 Jan 2013 03:05:37 -0500, q66 <quaker66 gmail.com> wrote:On Wednesday, 30 January 2013 at 03:02:38 UTC, deadalnix wrote:Apparently not the designers of objective-C. -SteveOn Wednesday, 30 January 2013 at 00:26:11 UTC, q66 wrote:It just gives another meaning to foo.bar, and ENFORCING camelCase by the language while lowercasing shit is just horrible. Anyone with a slightest trace of language design sense realizes that.It deeply disturbs me that people even take the original post seriously.Well, you may give some arguments instead of no, just no, to convince people.
Jan 30 2013
On Thursday, 31 January 2013 at 00:54:54 UTC, Steven Schveighoffer wrote:On Wed, 30 Jan 2013 03:05:37 -0500, q66 <quaker66 gmail.com> wrote:Not contradictory, Objective-C is not a well designed language :)On Wednesday, 30 January 2013 at 03:02:38 UTC, deadalnix wrote:Apparently not the designers of objective-C. -SteveOn Wednesday, 30 January 2013 at 00:26:11 UTC, q66 wrote:It just gives another meaning to foo.bar, and ENFORCING camelCase by the language while lowercasing shit is just horrible. Anyone with a slightest trace of language design sense realizes that.It deeply disturbs me that people even take the original post seriously.Well, you may give some arguments instead of no, just no, to convince people.
Jan 31 2013
On Thu, 31 Jan 2013 08:14:15 -0500, q66 <quaker66 gmail.com> wrote:On Thursday, 31 January 2013 at 00:54:54 UTC, Steven Schveighoffer wrote:Now we're just name calling ;) I tend to think that for the most successful company in the business to standardize on it is a pretty good testimony to it being well designed. I certainly have grown fond of it, there are some really nice features in it. But truly, xcode has played a large role in making the language seem good. As another option, what about changing my proposal so instead of setX, it's set_x, and then casing concerns are eliminated? I think C++.net does that. -SteveOn Wed, 30 Jan 2013 03:05:37 -0500, q66 <quaker66 gmail.com> wrote:Not contradictory, Objective-C is not a well designed language :)On Wednesday, 30 January 2013 at 03:02:38 UTC, deadalnix wrote:Apparently not the designers of objective-C. -SteveOn Wednesday, 30 January 2013 at 00:26:11 UTC, q66 wrote:It just gives another meaning to foo.bar, and ENFORCING camelCase by the language while lowercasing shit is just horrible. Anyone with a slightest trace of language design sense realizes that.It deeply disturbs me that people even take the original post seriously.Well, you may give some arguments instead of no, just no, to convince people.
Jan 31 2013
Now we're just name calling ;) I tend to think that for the most successful company in the business to standardize on it is a pretty good testimony to it being well designed.This is a really bad argument. The facts that language is being used by a large companies does not make it well designed. See PHP, for example - a *horrible* mess of a language, but it is being used at Facebook. (I don't have an opinion on objective C though, as I don't know the language)
Jan 31 2013
On Thu, 31 Jan 2013 14:39:56 -0000, jerro <a a.com> wrote:Small point. "using" != "standadized on". The latter implies some evaluation and decision making was done prior to the choice, the former.. well..Now we're just name calling ;) I tend to think that for the most successful company in the business to standardize on it is a pretty good testimony to it being well designed.This is a really bad argument. The facts that language is being used by a large companies does not make it well designed. See PHP, for example - a *horrible* mess of a language, but it is being used at Facebook.(I don't have an opinion on objective C though, as I don't know the language)Neither. R -- Using Opera's revolutionary email client: http://www.opera.com/mail/
Jan 31 2013
On Thursday, 31 January 2013 at 14:48:15 UTC, Regan Heath wrote:On Thu, 31 Jan 2013 14:39:56 -0000, jerro <a a.com> wrote:I bet the reason why Objective-C was chosen rather than C++ has more to do with licensing issues (LLVM wasn't rady at the time) and maybe GC than any other reason.Small point. "using" != "standadized on". The latter implies some evaluation and decision making was done prior to the choice, the former.. well..Now we're just name calling ;) I tend to think that for the most successful company in the business to standardize on it is a pretty good testimony to it being well designed.This is a really bad argument. The facts that language is being used by a large companies does not make it well designed. See PHP, for example - a *horrible* mess of a language, but it is being used at Facebook.(I don't have an opinion on objective C though, as I don't know the language)Neither. R
Feb 02 2013
On Thu, 31 Jan 2013 09:39:56 -0500, jerro <a a.com> wrote:From what I remember Andrei saying, they write their code in C++ and compile it to php, or something like that. Besides, facebook was a pet project by a single person that accidentally grew into an empire. Apple was around long before Steve Jobs brought Next Step OS (and it's usage of Objective-C) to Apple to become MacOS. You can't really argue that Mac is a horrible OS, it may not suit your tastes, but it performs well. Nick, please ignore this thread. -SteveNow we're just name calling ;) I tend to think that for the most successful company in the business to standardize on it is a pretty good testimony to it being well designed.This is a really bad argument. The facts that language is being used by a large companies does not make it well designed. See PHP, for example - a *horrible* mess of a language, but it is being used at Facebook.
Jan 31 2013
On 2013-01-31 15:56, Steven Schveighoffer wrote:From what I remember Andrei saying, they write their code in C++ and compile it to php, or something like that.I'm pretty sure it's the opposite. PHP code compiles to C++. "HipHop programmatically transforms your PHP source code into highly optimized C++ and then uses g++ to compile it." http://developers.facebook.com/blog/post/2010/02/02/hiphop-for-php--move-fast/ -- /Jacob Carlborg
Jan 31 2013
On 1/31/13 11:36 AM, Jacob Carlborg wrote:On 2013-01-31 15:56, Steven Schveighoffer wrote:We use JITting right now: https://www.facebook.com/note.php?note_id=10150415177928920 I'm that team! AndreiFrom what I remember Andrei saying, they write their code in C++ and compile it to php, or something like that.I'm pretty sure it's the opposite. PHP code compiles to C++. "HipHop programmatically transforms your PHP source code into highly optimized C++ and then uses g++ to compile it." http://developers.facebook.com/blog/post/2010/02/02/hiphop-for-php--move-fast/
Jan 31 2013
On 1/31/13 12:08 PM, Andrei Alexandrescu wrote:I'm that team!s/that/on that/
Jan 31 2013
On 2013-01-31 18:08, Andrei Alexandrescu wrote:We use JITting right now: https://www.facebook.com/note.php?note_id=10150415177928920Aha, I didn't know that. -- /Jacob Carlborg
Jan 31 2013
On 01/31/2013 03:56 PM, Steven Schveighoffer wrote:...See PHP, forOther way round!example - a *horrible* mess of a language, but it is being used at Facebook.From what I remember Andrei saying, they write their code in C++ and compile it to php, or something like that. ...
Jan 31 2013
On Thursday, 31 January 2013 at 14:28:39 UTC, Steven Schveighoffer wrote:On Thu, 31 Jan 2013 08:14:15 -0500, q66 <quaker66 gmail.com> wrote:No, that is not a solution either. Any of these setBlah or set_blah or whatever are ugly hacks. There should be explicit property syntax. By explicit, I mean explicit - at least likeOn Thursday, 31 January 2013 at 00:54:54 UTC, Steven Schveighoffer wrote:Now we're just name calling ;) I tend to think that for the most successful company in the business to standardize on it is a pretty good testimony to it being well designed. I certainly have grown fond of it, there are some really nice features in it. But truly, xcode has played a large role in making the language seem good. As another option, what about changing my proposal so instead of setX, it's set_x, and then casing concerns are eliminated? I think C++.net does that. -SteveOn Wed, 30 Jan 2013 03:05:37 -0500, q66 <quaker66 gmail.com> wrote:Not contradictory, Objective-C is not a well designed language :)On Wednesday, 30 January 2013 at 03:02:38 UTC, deadalnix wrote:Apparently not the designers of objective-C. -SteveOn Wednesday, 30 January 2013 at 00:26:11 UTC, q66 wrote:It just gives another meaning to foo.bar, and ENFORCING camelCase by the language while lowercasing shit is just horrible. Anyone with a slightest trace of language design sense realizes that.It deeply disturbs me that people even take the original post seriously.Well, you may give some arguments instead of no, just no, to convince people.
Jan 31 2013
On Thu, 31 Jan 2013 09:57:12 -0500, q66 <quaker66 gmail.com> wrote:On Thursday, 31 January 2013 at 14:28:39 UTC, Steven Schveighoffer wrote:I don't agree, the benefit of being able to refer to the property as a function and as a property separately is nice. For instance, you can get a delegate for the property. The other benefit is that the setBlah or set_blah functions are self-descriptive as properties. You would be hard pressed to argue such a function doesn't set a value called blah.As another option, what about changing my proposal so instead of setX, it's set_x, and then casing concerns are eliminated? I think C++.net does that. -SteveNo, that is not a solution either. Any of these setBlah or set_blah or whatever are ugly hacks.There should be explicit property syntax. By explicit, I mean explicit -I would be fine with that too, but with all due respect, the only person whose opinion matters is Walter. If he is possibly interested in any of these proposals instead of property, I think that's the one we should go for.Why don't we start with a language you DO like that has properties? Or are you sour on all of them? -Steve
Jan 31 2013
On 2013-01-31 15:28, Steven Schveighoffer wrote:Now we're just name calling ;) I tend to think that for the most successful company in the business to standardize on it is a pretty good testimony to it being well designed. I certainly have grown fond of it, there are some really nice features in it. But truly, xcode has played a large role in making the language seem good.And that is thanks to Clang and LLVM. Xcode wouldn't be nearly as good on autocompletion, refactoring and static analysis to mention a few features. Also it has started to catch up in later years, thinking of Objective-C 2. More recently blocks, some kind of operator overloading and more object literals. -- /Jacob Carlborg
Jan 31 2013
On Tue, 29 Jan 2013 19:26:09 -0500, q66 <quaker66 gmail.com> wrote:It deeply disturbs me that people even take the original post seriously.Sorry it offends you, but maybe you could have a constructive comment instead of a condescending tone? This is not a frivolous proposal, and it's not my first, but I'm trying to fit something with the language designers who have expressed a significant distaste with property to the point where they just want to go back to the crap we had before. If we can get ANY kind of property syntax, I think it's better than that. -Steve
Jan 30 2013
On Wednesday, 30 January 2013 at 00:25:41 UTC, Jonathan M Davis wrote:I believe that two main things are needed: 1. Make it possible to mark a variable such that you can't do anything with it that you couldn't do with a property function (e.g. taking its address needs to be illegal). 2. Add property rewrites to make it so that stuff like ++ and += work. You'll never get a property function to operate 100% like a variable, but you making variables and property functions swappable because it do stuff like let you take the address of a variable or a function. We basically need to do the same by restricting variables which are properties and improving the rewrites that the compile does for property functions. - Jonathan M DavisI agree partial emulation can work, and I see you've pointed out that the usage of a property will have to be restricted so that it can work, but this means you have to mark your naked variables as property ahead of time, otherwise you'll discover that you cannot replace a naked variable with a property without doing plenty of re-work. Given that we won't be able to drop in a property without rework unless preplanned ahead of time, I'm not so sure we'll be gaining anything new here with specially marked properties, and even if we could drop them in, I'm still not sure it's a big gain. I can see some value I suppose if you can mark a naked variable as property because you know it will likely be wrapped into a function call later but don't want to implement the wrappers immediately, but I don't know if that's something a lot of people really need or care that much about. I find the discussion we're having in another thread on the possibility of using a struct-like implementation for gaining property-like behaviors much more compelling a change for D because it extends D with interesting ways to implement variables and functions that can be used in more generalized situations AND it solves the property implementation issues too (in similar "restricted" ways as you've suggested can be done). See last few posts ... http://forum.dlang.org/thread/kdukid$stg$1 digitalmars.com If we can not only implement property as hoped for, but also get more expressive language features introduced along with it, then it may be something worth doing. --rt
Jan 29 2013
On Wed, Jan 30, 2013 at 01:58:16AM +0100, Rob T wrote: [...]I agree partial emulation can work, and I see you've pointed out that the usage of a property will have to be restricted so that it can work, but this means you have to mark your naked variables as property ahead of time, otherwise you'll discover that you cannot replace a naked variable with a property without doing plenty of re-work.[...] Why do you have to mark naked variables as property? Isn't that redundant? As for using struct to implement property, I like the idea, but it does raise tricky issues about how struct methods reference the parent lexical scope. I don't think it's as simple as just rewriting 'this' to point to the outer scope instead, because it breaks language expectations that 'this' should refer to the immediately-containing struct/class. There's bound to be corner cases that will break because of this. Consider, for example, what happens if the inner struct's methods need to call opAssign of the parent struct for whatever reason. There's also the consideration of what happens if you take the address of the 'pseudo' variable: the inner struct would then be effectively dissociated from the parent struct, and you'll need that hidden context pointer (along with its gotchas) in order to have things still work as before. T -- The volume of a pizza of thickness a and radius z can be described by the following formula: pi zz a. -- Wouter Verhelst
Jan 29 2013
On Wednesday, 30 January 2013 at 01:09:12 UTC, H. S. Teoh wrote:As for using struct to implement property, I like the idea, but it does raise tricky issues about how struct methods reference the parent lexical scope. I don't think it's as simple as just rewriting 'this' to point to the outer scope instead, because it breaks language expectations that 'this' should refer to the immediately-containing struct/class. There's bound to be corner cases that will break because of this. Consider, for example, what happens if the inner struct's methods need to call opAssign of the parent struct for whatever reason.outer.this outer.opAssignThere's also the consideration of what happens if you take the address of the 'pseudo' variable: the inner struct would then be effectively dissociated from the parent struct, and you'll need that hidden context pointer (along with its gotchas) in order to have things still work as before.Compiler detects a struct which holds no data of its own and disallows taking its address.
Jan 29 2013
On Wednesday, 30 January 2013 at 01:20:39 UTC, Zach the Mystic wrote:On Wednesday, 30 January 2013 at 01:09:12 UTC, H. S. Teoh wrote:Actually, you're right. I see no overloading of the address operator in the documentation. I doubt it's an insurmountable problem, though. opAddress?There's also the consideration of what happens if you take the address of the 'pseudo' variable: the inner struct would then be effectively dissociated from the parent struct, and you'll need that hidden context pointer (along with its gotchas) in order to have things still work as before.Compiler detects a struct which holds no data of its own and disallows taking its address.
Jan 29 2013
On Tuesday, January 29, 2013 17:06:32 H. S. Teoh wrote:Why do you have to mark naked variables as property? Isn't that redundant?In order to restrict what you can do with it to the subset of operations that you can do with a property function. In particular, taking its address would need to be illegal, as that won't work with a property function (or if it did, it would return a different type). It would be impossible to replace a normal variable with a property function without risking breaking code, because there are operations that you can normally do on a variable that couldn't possibly be implemented with a function (such as taking its address). But if you mark it to restrict what it can do, then you could swap it out with a function later without the risk of breaking code (which is one of the main reasons for having properties in the first place). property doesn't currently do this, but it could, and if we don't have something like that, then it'll never be safe to swap variables and property functions. - Jonathan M Davis
Jan 29 2013
On Wed, Jan 30, 2013 at 02:23:26AM +0100, Jonathan M Davis wrote:On Tuesday, January 29, 2013 17:06:32 H. S. Teoh wrote:I see.Why do you have to mark naked variables as property? Isn't that redundant?In order to restrict what you can do with it to the subset of operations that you can do with a property function. In particular, taking its address would need to be illegal, as that won't work with a property function (or if it did, it would return a different type).It would be impossible to replace a normal variable with a property function without risking breaking code, because there are operations that you can normally do on a variable that couldn't possibly be implemented with a function (such as taking its address). But if you mark it to restrict what it can do, then you could swap it out with a function later without the risk of breaking code (which is one of the main reasons for having properties in the first place). property doesn't currently do this, but it could, and if we don't have something like that, then it'll never be safe to swap variables and property functions.[...] If this is the case, then I would have to say that property is fundamentally broken. The whole point of property is to make functions behave like variables, but if this "variable emulation" isn't even complete, then it defeats the purpose of having it in the first place. T -- Just because you survived after you did it, doesn't mean it wasn't stupid!
Jan 29 2013
On Tue, 29 Jan 2013 17:32:20 -0800, H. S. Teoh <hsteoh quickfur.ath.cx> wrote:On Wed, Jan 30, 2013 at 02:23:26AM +0100, Jonathan M Davis wrote:Indeed, but a better idea would be to fix it, throwing it out seems a bit extreme. -- Adam Wilson IRC: LightBender Project Coordinator The Horizon Project http://www.thehorizonproject.org/On Tuesday, January 29, 2013 17:06:32 H. S. Teoh wrote:I see.Why do you have to mark naked variables as property? Isn't that redundant?In order to restrict what you can do with it to the subset of operations that you can do with a property function. In particular, taking its address would need to be illegal, as that won't work with a property function (or if it did, it would return a different type).It would be impossible to replace a normal variable with a property function without risking breaking code, because there are operations that you can normally do on a variable that couldn't possibly be implemented with a function (such as taking its address). But if you mark it to restrict what it can do, then you could swap it out with a function later without the risk of breaking code (which is one of the main reasons for having properties in the first place). property doesn't currently do this, but it could, and if we don't have something like that, then it'll never be safe to swap variables and property functions.[...] If this is the case, then I would have to say that property is fundamentally broken. The whole point of property is to make functions behave like variables, but if this "variable emulation" isn't even complete, then it defeats the purpose of having it in the first place. T
Jan 29 2013
On Tue, Jan 29, 2013 at 06:05:15PM -0800, Adam Wilson wrote:On Tue, 29 Jan 2013 17:32:20 -0800, H. S. Teoh <hsteoh quickfur.ath.cx> wrote:[...]On Wed, Jan 30, 2013 at 02:23:26AM +0100, Jonathan M Davis wrote:On Tuesday, January 29, 2013 17:06:32 H. S. Teoh wrote:I see.Why do you have to mark naked variables as property? Isn't that redundant?In order to restrict what you can do with it to the subset of operations that you can do with a property function. In particular, taking its address would need to be illegal, as that won't work with a property function (or if it did, it would return a different type).It would be impossible to replace a normal variable with a property function without risking breaking code, because there are operations that you can normally do on a variable that couldn't possibly be implemented with a function (such as taking its address). But if you mark it to restrict what it can do, then you could swap it out with a function later without the risk of breaking code (which is one of the main reasons for having properties in the first place). property doesn't currently do this, but it could, and if we don't have something like that, then it'll never be safe to swap variables and property functions.[...] If this is the case, then I would have to say that property is fundamentally broken. The whole point of property is to make functions behave like variables, but if this "variable emulation" isn't even complete, then it defeats the purpose of having it in the first place.Indeed, but a better idea would be to fix it, throwing it out seems a bit extreme.[...] I'm not for throwing it out, actually. :) Just pointing out some problematic aspects of it. One way to solve the '&' problem is to have the compiler lower that into a delegate that gives access to the setter/getter for that field. Then property *would* indeed be a drop-in replacement for member variables. T -- In theory, there is no difference between theory and practice.
Jan 29 2013
On 01/29/2013 09:13 PM, H. S. Teoh wrote:I'm not for throwing it out, actually. :) Just pointing out some problematic aspects of it. One way to solve the '&' problem is to have the compiler lower that into a delegate that gives access to the setter/getter for that field. Then property *would* indeed be a drop-in replacement for member variables. TI hate to be a bringer of bad news, but I don't think getter/setter proxies will ever be an invisible replacement for pointers. Getter/setter proxies cannot be incremented/decremented, and you can't use them in conjunction with the container's pointer to get the offset to the field. Pointers have very specific semantics. I think it's much easier to just restrict variables from being addressable in cases where they will eventually become properties. I would argue though, that pointers are a getter/setter proxy. The relationship is just not commutative. What this means is that we can treat getter/setter proxies as an algorithmic structure, right alongside things like ranges, iterators, containers, etc. They are the most general form of their class: anything that supports assignment and retrieval (ex: pointers) is a kind of getter/setter proxy. I think that we would eventually want a (library-defined) getter/setter proxy type. It will be the only way to defer getting/setting of an property into called code, which is what pointers are currently used for in many cases. Such a type should be possible to construct from plain variables, pointers, (hash table + key) pairs, certain functions (ex: foo(int getOrSet, void **value)), and anything else you could concoct that satisfies the "is a" relationship. </dream>
Jan 29 2013
On Tue, Jan 29, 2013 at 09:44:36PM -0500, Chad Joan wrote:On 01/29/2013 09:13 PM, H. S. Teoh wrote:[...]I'm not for throwing it out, actually. :) Just pointing out some problematic aspects of it. One way to solve the '&' problem is to have the compiler lower that into a delegate that gives access to the setter/getter for that field. Then property *would* indeed be a drop-in replacement for member variables.I hate to be a bringer of bad news, but I don't think getter/setter proxies will ever be an invisible replacement for pointers. Getter/setter proxies cannot be incremented/decremented,This is easy to fix in the compiler.and you can't use them in conjunction with the container's pointer to get the offset to the field. Pointers have very specific semantics.If you write code that is specific to a particular implementation of a field, then it's no surprise that you can't use drop-in abstract replacements. I don't see that as a major issue.I think it's much easier to just restrict variables from being addressable in cases where they will eventually become properties.You're right, there is some merit to this idea.I would argue though, that pointers are a getter/setter proxy. The relationship is just not commutative. What this means is that we can treat getter/setter proxies as an algorithmic structure, right alongside things like ranges, iterators, containers, etc. They are the most general form of their class: anything that supports assignment and retrieval (ex: pointers) is a kind of getter/setter proxy.I like this line of reasoning. Pointer arithmetic is unsafe anyway, and in general don't interact well with abstraction, so I don't see lack of pointer support as a major problem. As long as you treat pointers as opaque handles to some value (abstract or otherwise), you can replace them with a getter/setter proxy.I think that we would eventually want a (library-defined) getter/setter proxy type. It will be the only way to defer getting/setting of an property into called code, which is what pointers are currently used for in many cases. Such a type should be possible to construct from plain variables, pointers, (hash table + key) pairs, certain functions (ex: foo(int getOrSet, void **value)), and anything else you could concoct that satisfies the "is a" relationship.[...] I think if we can address the various issues of Rob T's struct-as-variable idea, it might be possible to turn it into a template in Phobos (maybe in std.typecons or something). T -- "I speak better English than this villain Bush" -- Mohammed Saeed al-Sahaf, Iraqi Minister of Information
Jan 29 2013
On Tuesday, January 29, 2013 18:13:41 H. S. Teoh wrote:I'm not for throwing it out, actually. :) Just pointing out some problematic aspects of it. One way to solve the '&' problem is to have the compiler lower that into a delegate that gives access to the setter/getter for that field. Then property *would* indeed be a drop-in replacement for member variables.But the type would be different. You wouldn't be able to do stuff like int* p = &s.prop; And what happens with a delegate is fundamentally different when you take the address of a variable. The property function may not even be returning a value associated with a variable. It could be calculated. I believe that you're trying to take the abstraction farther than is possible. All abstractions break at some point, and taking the address of a property is one place that property functions break as an abstraction for variables. - Jonathan M Davis
Jan 29 2013
On Wednesday, 30 January 2013 at 00:25:41 UTC, Jonathan M Davis wrote:On Wednesday, January 30, 2013 00:55:13 Rob T wrote:I always thought that having public member variables is a bad style of programming because of the lack of encapsulation. So, if there's a language feature that enables you to write public member variables, and later on, replace them with property functions, wouldn't that mean that the language is encouraging this particular kind of bad style of programming?[..] You know a lot more about implementing compiler magic than I do, so I'll ask you if you think the effort is doable enough to justify having property functions that can act like a drop in replacement for existing variables?I believe that two main things are needed: [..]
Jan 29 2013
On Wed, Jan 30, 2013 at 02:40:45AM +0100, TommiT wrote:On Wednesday, 30 January 2013 at 00:25:41 UTC, Jonathan M Davis wrote:Property functions are precisely what gives you encapsulation. Think about it. They let you "pretend" that there's a public member variable, but actually you don't know (and don't have to know) what their real implementation is. This is, by definition, encapsulation. So this is actually an argument *for*, rather than against, property functions. There's nothing wrong with public member variables per se, it's the fact that it makes external code rely on their specific implementation. Property functions alleviate this problem by making it possible to change the underlying implementation without needing to touch user code. T -- The fact that anyone still uses AOL shows that even the presence of options doesn't stop some people from picking the pessimal one. - Mike EllisOn Wednesday, January 30, 2013 00:55:13 Rob T wrote:I always thought that having public member variables is a bad style of programming because of the lack of encapsulation. So, if there's a language feature that enables you to write public member variables, and later on, replace them with property functions, wouldn't that mean that the language is encouraging this particular kind of bad style of programming?[..] You know a lot more about implementing compiler magic than I do, so I'll ask you if you think the effort is doable enough to justify having property functions that can act like a drop in replacement for existing variables?I believe that two main things are needed: [..]
Jan 29 2013
On Tue, 29 Jan 2013 17:40:45 -0800, TommiT <tommitissari hotmail.com> wrote:On Wednesday, 30 January 2013 at 00:25:41 UTC, Jonathan M Davis wrote:Not really, public fields ARE bad, but properties allow you to sanitize the data and throw exceptions if the data doesn't fit the spec. A field does not. In this way encapsulation is maintained. -- Adam Wilson IRC: LightBender Project Coordinator The Horizon Project http://www.thehorizonproject.org/On Wednesday, January 30, 2013 00:55:13 Rob T wrote:I always thought that having public member variables is a bad style of programming because of the lack of encapsulation. So, if there's a language feature that enables you to write public member variables, and later on, replace them with property functions, wouldn't that mean that the language is encouraging this particular kind of bad style of programming?[..] You know a lot more about implementing compiler magic than I do, so I'll ask you if you think the effort is doable enough to justify having property functions that can act like a drop in replacement for existing variables?I believe that two main things are needed: [..]
Jan 29 2013
On Wednesday, 30 January 2013 at 01:40:52 UTC, TommiT wrote:On Wednesday, 30 January 2013 at 00:25:41 UTC, Jonathan M Davis wrote:Well, the main reason why this was bad convention, is because the "." operator conceptually returns by reference, so you are operating directly on the encapsulated variable with no possibility of oversight through the encapsulation. The property method will restrict variable usage to non-ref and non-pointer uses only, which is a form of encapsulation through the "." operator, and it can later be replaced with a function call if required. Even with property restrictions, I still don't think it will work as expected. For example, if the variable is a struct, then you have to disallow operations on the struct from outside. Example: struct Y { int a; } struct X{ property Y y; } X x; x.y.a = 4; // <- this has to be illegal! Reason? struct X{ Y _y; property Y y{ return _y; } } // this won't change _y as it did before. x.y.a = 4; I figure if we're going to do something about properties, we may as well do something much more compelling and re-invent the property rather than attempt to partially emulate variables just because someone was in a hurry and left their encapsulated variables public and used them directly outside the struct or class. --rtOn Wednesday, January 30, 2013 00:55:13 Rob T wrote:I always thought that having public member variables is a bad style of programming because of the lack of encapsulation. So, if there's a language feature that enables you to write public member variables, and later on, replace them with property functions, wouldn't that mean that the language is encouraging this particular kind of bad style of programming?[..] You know a lot more about implementing compiler magic than I do, so I'll ask you if you think the effort is doable enough to justify having property functions that can act like a drop in replacement for existing variables?I believe that two main things are needed: [..]
Jan 29 2013
On Wednesday, 30 January 2013 at 02:15:09 UTC, Rob T wrote:Even with property restrictions, I still don't think it will work as expected. For example, if the variable is a struct, then you have to disallow operations on the struct from outside. Example: struct Y { int a; } struct X{ property Y y; } X x; x.y.a = 4; // <- this has to be illegal! Reason? struct X{ Y _y; property Y y{ return _y; } } // this won't change _y as it did before. x.y.a = 4;Somehow I had missed this post. So, we can bury the idea of restricting the access to a public member variable by making it illegal to take the address of it. And as long as it is possible to take the address of a public member variable, it is possible for the end-user to by-pass all encapsulation that you might later on add over that public member variable. For this reason, my logic says, it is impossible to invent such an implementation of property concept that would make it possible to first put in a public member variable and later on encapsulate it *without* changing the interface.
Jan 30 2013
On Wednesday, 30 January 2013 at 12:04:31 UTC, TommiT wrote:[..] it is impossible to invent such an implementation of property concept that would make it possible to first put in a public member variable and later on encapsulate it *without* changing the interface.And frankly, I think it's a good thing. Because this way we can add to D's documentation: "NOTE: properties are *not* inter-changeable with public member variables", and thus, actively discourage people from writing un-encapsulated interfaces which expose public member variables.
Jan 30 2013
On Wednesday, 30 January 2013 at 12:11:30 UTC, TommiT wrote:Because this way we can add to D's documentation: "NOTE: properties are *not* inter-changeable with public member variables", and thus, actively discourage people from writing un-encapsulated interfaces which expose public member variables.The moral of the story: We should all stop thinking of properties as data, and start thinking properties as functions that you call with a data-like interface. The value of properties is in clearer semantics: Separate accessor and mutator are tied together very loosely, that is, only by the similarity in their naming: getSomething, setSomething. Whereas property getter and setter have the same name, and thus are semantically un-ambiguously tied together.
Jan 30 2013
On 2013-01-30 03:15, Rob T wrote:Even with property restrictions, I still don't think it will work as expected. For example, if the variable is a struct, then you have to disallow operations on the struct from outside. Example: struct Y { int a; } struct X{ property Y y; } X x; x.y.a = 4; // <- this has to be illegal! Reason? struct X{ Y _y; property Y y{ return _y; } } // this won't change _y as it did before. x.y.a = 4;That would require some property rewrite by the compiler. -- /Jacob Carlborg
Jan 30 2013
On Wednesday, January 30, 2013 02:40:45 TommiT wrote:On Wednesday, 30 January 2013 at 00:25:41 UTC, Jonathan M Davis wrote:Aside from the ability to take the variable's address, what really is the difference between struct S { int prop; } and struct S { property int prop() safe const pure nothrow { return _prop; } property int prop(int value) safe const pure nothrow { return _prop = value; } private int _prop; } At the moment, stuff like ++ and += wouldn't work with property, but that could be fixed. But as far as access goes, there's no real difference. You have full read-write access in both cases. That being the case, why bother with the do, but we can't with our current implementation of properties), is start with struct S { int prop; } The code's shorter and simpler. You don't need any checks on the data, and you don't need to do any operations when the property gets set. So, a variable is just fine. Then when you actually need to do something extra when the property is set, you change it to a property function. struct S { property int prop() safe const pure nothrow { return _prop; } property int prop(int value) safe const pure nothrow { validate(value); _prop = value; doSomethingElseWhichCaresAboutPropChanging(); return _prop; } private int _prop; } actually have a good property implementation, and you can't take the address so that the compiler does proper rewriting of code like s.prop++ and make it so that we can mark variables as properties (so that you can't take their address or pass them by ref or do anything else that you can't do with a property function). e.g. struct S { property int prop; } But a public variable isn't a problem if the language allows you to swap it out with a property function without breaking code. - Jonathan M DavisOn Wednesday, January 30, 2013 00:55:13 Rob T wrote:I always thought that having public member variables is a bad style of programming because of the lack of encapsulation. So, if there's a language feature that enables you to write public member variables, and later on, replace them with property functions, wouldn't that mean that the language is encouraging this particular kind of bad style of programming?[..] You know a lot more about implementing compiler magic than I do, so I'll ask you if you think the effort is doable enough to justify having property functions that can act like a drop in replacement for existing variables?I believe that two main things are needed: [..]
Jan 29 2013
On Wednesday, 30 January 2013 at 02:22:14 UTC, Jonathan M Davis wrote:On Wednesday, January 30, 2013 02:40:45 TommiT wrote:Okay, I can see how that could work. But I still stand un-corrected by my previous post. Because 'public' means to me: "end-user has direct all-access". Therefore: "public property int prop;" isn't really public given my definition. It's somewhere in the space between public and private.I always thought that having public member variables is a bad style of programming because of the lack of encapsulation. So, if there's a language feature that enables you to write public member variables, and later on, replace them with property functions, wouldn't that mean that the language is encouraging this particular kind of bad style of programming?Aside from the ability to take the variable's address, what really is the difference between struct S { int prop; } and struct S { property int prop() safe const pure nothrow { return _prop; } property int prop(int value) safe const pure nothrow { return _prop = value; } private int _prop; } At the moment, stuff like ++ and += wouldn't work with property, but that could be fixed. But as far as access goes, there's no real difference. You have full read-write access in both cases. That being the case, why bother with the property functions? What you're supposed to be able to do (and do, but we can't with our current implementation of properties), is start with struct S { int prop; } The code's shorter and simpler. You don't need any checks on the data, and you don't need to do any operations when the property gets set. So, a variable is just fine. Then when you actually need to do something extra when the property is set, you change it to a property function. struct S { property int prop() safe const pure nothrow { return _prop; } property int prop(int value) safe const pure nothrow { validate(value); _prop = value; doSomethingElseWhichCaresAboutPropChanging(); return _prop; } private int _prop; } because they actually have a good property implementation, and you can't take the address need to fix it so that the compiler does proper rewriting of code like s.prop++ and make it so that we can mark variables as properties (so that you can't take their address or pass them by ref or do anything else that you can't do with a property function). e.g. struct S { property int prop; } But a public variable isn't a problem if the language allows you to swap it out with a property function without breaking code. - Jonathan M Davis
Jan 29 2013
On 01/29/2013 08:40 PM, TommiT wrote:On Wednesday, 30 January 2013 at 00:25:41 UTC, Jonathan M Davis wrote:No, it means that style of programming is no longer bad. It is already possible to write public member variables. It's pretty much as dangerous to do so as the wisdom says. We avoid using public member variables specifically because, in most languages, this makes it impossible to add hooks into the assignment/retrieval of the variable later without breaking the API. Now, in D, we might one day be able to add those assignment/retrieval hooks onto a variable without breaking API. That makes it no longer necessary to avoid public variables, though you will probably have to mark them property to get the safety.On Wednesday, January 30, 2013 00:55:13 Rob T wrote:I always thought that having public member variables is a bad style of programming because of the lack of encapsulation. So, if there's a language feature that enables you to write public member variables, and later on, replace them with property functions, wouldn't that mean that the language is encouraging this particular kind of bad style of programming?[..] You know a lot more about implementing compiler magic than I do, so I'll ask you if you think the effort is doable enough to justify having property functions that can act like a drop in replacement for existing variables?I believe that two main things are needed: [..]
Jan 29 2013
On Wednesday, 30 January 2013 at 01:40:52 UTC, TommiT wrote:On Wednesday, 30 January 2013 at 00:25:41 UTC, Jonathan M Davis wrote:Belief is rarely a good thing. public variable are an encapsulation problem if you don't have properties. Then, a bunch of boilerplate is written because in 1% of the cases, some logic will be hooked on the variable access. Allowing properties allow the same level of encapsulation, without requiring boilerplate up-front.On Wednesday, January 30, 2013 00:55:13 Rob T wrote:I always thought that having public member variables is a bad style of programming because of the lack of encapsulation. So, if there's a language feature that enables you to write public member variables, and later on, replace them with property functions, wouldn't that mean that the language is encouraging this particular kind of bad style of programming?[..] You know a lot more about implementing compiler magic than I do, so I'll ask you if you think the effort is doable enough to justify having property functions that can act like a drop in replacement for existing variables?I believe that two main things are needed: [..]
Jan 29 2013
On Wednesday, 30 January 2013 at 03:24:47 UTC, deadalnix wrote:public variable are an encapsulation problem if you don't have properties.I don't agree. I think public variables are an encapsulation problem, period. And again, by 'public' I mean: "really, truly public, not kidding".
Jan 29 2013
On Wednesday, 30 January 2013 at 03:52:22 UTC, TommiT wrote:On Wednesday, 30 January 2013 at 03:24:47 UTC, deadalnix wrote:Sounds like religious reasoning.public variable are an encapsulation problem if you don't have properties.I don't agree. I think public variables are an encapsulation problem, period. And again, by 'public' I mean: "really, truly public, not kidding".
Jan 29 2013
On Wednesday, 30 January 2013 at 04:06:02 UTC, deadalnix wrote:I don't understand you. According to wikipedia, encapsulation is: "A language mechanism for restricting access to some of the object's components." Member variable is a component of an object. Public access means un-restricted access. Therefore, public member variable is not encapsulated. Therefore, public member variable is a problem in encapsulation, by definition. I dare you to find a single religious cell in me.I don't agree. I think public variables are an encapsulation problem, period. And again, by 'public' I mean: "really, truly public, not kidding".Sounds like religious reasoning.
Jan 29 2013
There's times when a member variable manages its own invariant and any of its values is valid for the containing class, in which case the container doesn't need to further restrict access to it; a public struct doesn't need to be wrapped in a get function or anything.
Jan 29 2013
On Wednesday, 30 January 2013 at 04:39:13 UTC, Adam D. Ruppe wrote:There's times when a member variable manages its own invariant and any of its values is valid for the containing class, in which case the container doesn't need to further restrict access to it; a public struct doesn't need to be wrapped in a get function or anything.Okay, so we have this: struct Foo { Bar bar; } Assume that all data in Bar is stack allocated and we can't change it. What if I later on realize, that I should have really allocated bar on the heap, because its size is too great and it makes Foo inconvenient in every-day use because of stack overflow problems. Now that everybody has already been using foo.bar directly, I feel really bad for not encapsulating it. Note: that's not a problem if we have a way of saying that bar should behave like a property function, something like: struct Foo { property Bar bar; } ...and if we can create that property function later on.
Jan 29 2013
On Wednesday, 30 January 2013 at 04:39:13 UTC, Adam D. Ruppe wrote:There's times when a member variable manages its own invariant and any of its values is valid for the containing class, in which case the container doesn't need to further restrict access to it.But yes, there are times, when a public member variable, which encapsulates its own data, is truly designed as a part of the interface, in which case it doesn't need to be encapsulated any further.
Jan 29 2013
On 1/29/13 8:40 PM, TommiT wrote:On Wednesday, 30 January 2013 at 00:25:41 UTC, Jonathan M Davis wrote:The thing here is that properties offer control over changing the variable, which makes all the difference. AndreiOn Wednesday, January 30, 2013 00:55:13 Rob T wrote:I always thought that having public member variables is a bad style of programming because of the lack of encapsulation. So, if there's a language feature that enables you to write public member variables, and later on, replace them with property functions, wouldn't that mean that the language is encouraging this particular kind of bad style of programming?[..] You know a lot more about implementing compiler magic than I do, so I'll ask you if you think the effort is doable enough to justify having property functions that can act like a drop in replacement for existing variables?I believe that two main things are needed: [..]
Jan 29 2013
On 2013-01-30 02:40, TommiT wrote:I always thought that having public member variables is a bad style of programming because of the lack of encapsulation. So, if there's a language feature that enables you to write public member variables, and later on, replace them with property functions, wouldn't that mean that the language is encouraging this particular kind of bad style of programming?I really don't see much point in properties/methods that just forwards to an instance variable. -- /Jacob Carlborg
Jan 30 2013
On 1/30/13 10:10 AM, Jacob Carlborg wrote:On 2013-01-30 02:40, TommiT wrote:Insurance. AndreiI always thought that having public member variables is a bad style of programming because of the lack of encapsulation. So, if there's a language feature that enables you to write public member variables, and later on, replace them with property functions, wouldn't that mean that the language is encouraging this particular kind of bad style of programming?I really don't see much point in properties/methods that just forwards to an instance variable.
Jan 30 2013
On Wednesday, 30 January 2013 at 15:10:37 UTC, Jacob Carlborg wrote:I really don't see much point in properties/methods that just forwards to an instance variable.I assume you mean something like this: struct S { private T _t; ref T get() { return _t; } void set(T t) { ... } } The benefit of the above type of coding versus having a public T variable, is that you can change the implementation of S without changing S's interface. Perhaps I would like to change it to this (or whatever): private static T[5] tees; struct S { private byte _idx; ref T get() { return tees[_idx]; } void set(T t) { ... } }
Jan 30 2013
On 2013-01-30 17:26, TommiT wrote:I assume you mean something like this: struct S { private T _t; ref T get() { return _t; } void set(T t) { ... } } The benefit of the above type of coding versus having a public T variable, is that you can change the implementation of S without changing S's interface. Perhaps I would like to change it to this (or whatever): private static T[5] tees; struct S { private byte _idx; ref T get() { return tees[_idx]; } void set(T t) { ... } }Sure, but I think that's what properties are for. We currently don't have that in D but I think it would be great if fields could be exchanged with methods without breaking the API. -- /Jacob Carlborg
Jan 30 2013
On Wednesday, 30 January 2013 at 20:28:32 UTC, Jacob Carlborg wrote:Sure, but I think that's what properties are for. We currently don't have that in D but I think it would be great if fields could be exchanged with methods without breaking the API.The problem is that genie is out of the bottle once you have committed yourself to an interface where there is a public member variable. And you can't put the genie back in the bottle any more. This means that your interface can't add any encapsulation over this public member variable afterwards without changing the interface.
Jan 30 2013
As interface api good practice is usage virtual public functions of classes. So, (virtual) properties add an additional usefulness.
Jan 30 2013
On Wednesday, 30 January 2013 at 21:07:56 UTC, TommiT wrote:The problem is that genie is out of the bottle once you have committed yourself to an interface where there is a public member variable. And you can't put the genie back in the bottle any more. This means that your interface can't add any encapsulation over this public member variable afterwards without changing the interface.A bit more code, a bit less metaphors: struct S { T data; } // end-user code: S s; *&s.data = 42; End-user thus by-passes any encapsulation that could be possible added over S.data field later on, like the following: struct S { private T _data; property ref T data() { return _data; } property ref T data(int v) { assert(v != 42); _data = v; return _data; } }
Jan 30 2013
On 01/30/2013 09:10 AM, Jacob Carlborg wrote:On 2013-01-30 02:40, TommiT wrote:Me either. I mean yes, for anything that is part of a public api you should probably double check everything. But insisting on getters and setters regardless of the requirements of what you are getting and setting? Sounds like an excuse to not think, to me.I always thought that having public member variables is a bad style of programming because of the lack of encapsulation. So, if there's a language feature that enables you to write public member variables, and later on, replace them with property functions, wouldn't that mean that the language is encouraging this particular kind of bad style of programming?I really don't see much point in properties/methods that just forwards to an instance variable.
Jan 30 2013
On Wednesday, 30 January 2013 at 21:26:34 UTC, 1100110 wrote:Me either. I mean yes, for anything that is part of a public api you should probably double check everything. But insisting on getters and setters regardless of the requirements of what you are getting and setting? Sounds like an excuse to not think, to me.Putting in public variables sounds like not thinking, to me. Interface should expose the minimum amount of access possible, whereas public variables expose the maximum amount of access.
Jan 30 2013
On Wednesday, January 30, 2013 15:26:32 1100110 wrote:On 01/30/2013 09:10 AM, Jacob Carlborg wrote:The main reason for it is that you can add additional code later when it no longer needs to just get or set the variable. But one of the goals of properties is to make it so that you can just make it a public variable to begin with and then swap it out with a property function later when you need to add code like that. However, that never quite seems to work perfectly, as there's always something that you can do with a variable that you can't do with a property function (e.g. take its address or pass it by ref). Without properties though, you definitely want the getters and setters so that you don't lock yourself out of being able to properly protect the variable when you actually need to later. - Jonathan m DavisOn 2013-01-30 02:40, TommiT wrote:Me either. I mean yes, for anything that is part of a public api you should probably double check everything. But insisting on getters and setters regardless of the requirements of what you are getting and setting? Sounds like an excuse to not think, to me.I always thought that having public member variables is a bad style of programming because of the lack of encapsulation. So, if there's a language feature that enables you to write public member variables, and later on, replace them with property functions, wouldn't that mean that the language is encouraging this particular kind of bad style of programming?I really don't see much point in properties/methods that just forwards to an instance variable.
Jan 30 2013
On Wednesday, 30 January 2013 at 00:25:41 UTC, Jonathan M Davis wrote:1. Make it possible to Mark a variable such that you can't do anything with it that you couldn't do with a property function (e.g. taking its address needs to be illegal).If we didn't have to interface with C and we were willing to get a little extra processing in order to use flags you could get away with this. In a 64Bit environment it seems plausible. I don't see this as an option realistically with everything as it is, however the potential can't be ignored. Let's say the top 4 bits of a pointer are flags, one for 'is stack' and one for 'is function ptr', etc. The function pointer referenced then then make properties work exactly like variables. Mind you likely a few extra flags may be needed to determine constness for safety, or two ptrs for a getter/setter (or just a small lookup table for a combination of them all). If these flags then are used and recognize that it has a function instead of a variable, it can call the function, however passing to C or anything expecting a variable then it would have to throw an error as there's no way for the D specific flags to be carried over and used safely. struct S { int _a; int a() {return a + 1;} int a(int setA) { _a = setA; return setA; } } Now: void func(ref int a) { a = 100; //real int always passes assert(a == 100); //can't assume true with function property pointer } S s; //passes, flag realizes it's a function that now is //treated as a variable for this purpose. func(s.a); extern(C) void cFunction(int *ptr); //fails, C unaware of handling function reference cFunction(s.a); //fails, same reason. cFunction(&s.a); Perhaps it's a small option that in compiling these flags can be made use of; Instantiation of templates the properties can be treated as variables correctly (invisibly), assuming it never passes a reference to anything it can't verify can handle it. But as before, this is just an idea, which won't be used in D.
Jan 30 2013
On 2013-01-30 00:55, Rob T wrote:Given how D currently works, I don't see how we can realistically implement a function as a drop in replacement for a variable and expect code to continue working as if nothing had changed. One of the bigger problems is that the getter returns by value, not ref, so everything that expects a ref return will fail. I expect to make precise variable emulation through properties will require a lot of compiler magic, and there will be inevitable bugs and conflicts that follow. I really don't see that there's enough value with the property concept to justify the costs of precise variable emulation. You know a lot more about implementing compiler magic than I do, so I'll ask you if you think the effort is doable enough to justify having property functions that can act like a drop in replacement for existing variables?Implement this: struct Foo { property int a; } Lowered to: struct Foo { private int a_; property int a () { return a_; } property int a (int value) { return a_ = value; } } -- /Jacob Carlborg
Jan 30 2013
On Tue, 29 Jan 2013 18:09:44 -0500, Jonathan M Davis <jmdavisProg gmx.com> wrote:On Tuesday, January 29, 2013 12:10:04 Steven Schveighoffer wrote:I don't think this is quite right. You can never *exactly* replace a field with a property, or vice versa. There are aspects that are different for both. But there are two separate cases here. One is, you define a property that is specific to a type, and then replace it with a field. The other is that there is a DEFINED API, and you replace it with a field. In the first case, yes, you would have to go through and replace () instances with ones that do not have it. If your documentation is clear, then it really is on the user to have made that mistake. With the idea I specified later where getX would require no parentheses, you could specify a property that could not be called like a function unless you use the getX version. But in the second case, consider for instance a range. A range has an empty field/property. If you called it via empty(), then your code is broken for all different types of ranges which use a field (or enum). In any case, I think there is no getting around that changing from a property to a field or vice versa will cause problems for existing code. -SteveSound crazy? Ridiculous? Impossible? Insulting?It seems like it could work, but without a way to explictly make something a getter property, it will be impossible to change a property function into a variable later without risking breaking code, because then people will still be able to call the property function with parens. Using parens on getter properties has to be illegal for that to work.
Jan 30 2013
On Wed, Jan 30, 2013 at 07:49:58PM -0500, Steven Schveighoffer wrote:On Tue, 29 Jan 2013 18:09:44 -0500, Jonathan M Davis <jmdavisProg gmx.com> wrote:[...] Actually, this got me thinking. The range API only requires that .empty evaluates to a bool, right? It doesn't matter if it's a function, a public variable, or an enum, as long as it evaluates (or can be evaluated) to a bool. Some ranges indeed do define .empty as an enum (c.f. infinite ranges), so you couldn't take the address of .empty. Now consider class/struct fields in general. It's entirely possible that a particular class starts off with some fields defined as enums (of the manifest constant sort), say as an enum string. Later on, you may decide that the value should be changeable, so you make it a string class variable. Yet later, you may decide to implement a getter/setter for it for whatever reason. In the process, the only time it's valid to take the address of the field is when it's a string variable. So in that sense, the API of the class really only should specify that field xyz is a value of type string; user code should not depend on its particular implementation (enum, variable, or getter). Marking fields as property is starting to make more and more sense. T -- BREAKFAST.COM halted...Cereal Port Not Responding. -- YHLOn Tuesday, January 29, 2013 12:10:04 Steven Schveighoffer wrote:I don't think this is quite right. You can never *exactly* replace a field with a property, or vice versa. There are aspects that are different for both. But there are two separate cases here. One is, you define a property that is specific to a type, and then replace it with a field. The other is that there is a DEFINED API, and you replace it with a field. In the first case, yes, you would have to go through and replace () instances with ones that do not have it. If your documentation is clear, then it really is on the user to have made that mistake. With the idea I specified later where getX would require no parentheses, you could specify a property that could not be called like a function unless you use the getX version. But in the second case, consider for instance a range. A range has an empty field/property. If you called it via empty(), then your code is broken for all different types of ranges which use a field (or enum).Sound crazy? Ridiculous? Impossible? Insulting?It seems like it could work, but without a way to explictly make something a getter property, it will be impossible to change a property function into a variable later without risking breaking code, because then people will still be able to call the property function with parens. Using parens on getter properties has to be illegal for that to work.
Jan 30 2013
On Tuesday, January 29, 2013 17:32:20 H. S. Teoh wrote:If this is the case, then I would have to say that property is fundamentally broken. The whole point of property is to make functions behave like variables, but if this "variable emulation" isn't even complete, then it defeats the purpose of having it in the first place.It works if you can restrict a variable to a reasonable subset of its normal operations (which primarily means that you can't take its address or pass it by ref). You just can't fix that. Not with a systems language like D. Variables have as much low-level control over variables (like taking their address). But if we can do something like struct S { Â Â property int prop; } then that fixes the problem. - Jonathan M Davis
Jan 29 2013
On Wednesday, 30 January 2013 at 02:29:12 UTC, Jonathan M Davis wrote:But if we can do something like struct S { Â Â property int prop; } then that fixes the problem.I had a thought. What if we use this opportunity to also fix the problem with transient ranges. So... what if, instead of using the attribute property for the purpose you suggest, we added a new attribute, let's say noref, and that's what it would mean: struct S { } S s; Transient ranges could notate their front method with noref, which would prevent all incorrect use of them, and would enable their front to return by ref or const ref, instead of by value.
Jan 29 2013
On 01/30/2013 03:29 AM, Jonathan M Davis wrote:Nope.
Jan 30 2013
On Wednesday, January 30, 2013 18:54:20 Timon Gehr wrote:On 01/30/2013 03:29 AM, Jonathan M Davis wrote:It was my understanding that it did. Everything that I've read on it indicated - Jonathan M DavisNope.
Jan 30 2013
On 01/30/2013 08:44 PM, Jonathan M Davis wrote:On Wednesday, January 30, 2013 18:54:20 Timon Gehr wrote:fields can.)On 01/30/2013 03:29 AM, Jonathan M Davis wrote:It was my understanding that it did. Everything that I've read on it indicated - Jonathan M DavisNope.
Jan 30 2013
On 2013-01-30 20:44, Jonathan M Davis wrote:It was my understanding that it did. Everything that I've read on it indicated-- /Jacob Carlborg
Jan 30 2013
Sorry I have to oppose this. It is in no way a compromise as it is completely different from everything suggested. I'm going to take this opportunity to highjack your thread. Can an pro- property members claim that the current behavior is what you want? I believe this answer is no. It seems at least some members for property feel that currently functions are being annotated with property that shouldn't be. It also seems those for property aren't fighting optional parens as much? Can we discuss fixing the issues we have with this. I think a good change is to require parens if returning a callable (opposite of Walters suggestion). -------------------- If I have my above claims mostly correct, then I'd say property needs to be put back in the drawing board and re-implemented. I'd be for removing it from the language and if we decide on what in needs to enforce and should be part of the language, then its implementation is completed in a feature branch and remains out of the language until it meets the needed enforcement and behavior. Granted I'm not concerned if it doesn't ever come back. I believe it has a legitimate role in allowing a change from field to function without harming usage that can not be achieved without an annotation. However it seems we can't achieve this with the combination of features D employs. I don't agree with the argument that properties provide a convince to identify low overhead access. While I'm not experienced in this area, profile code should indicate where performance is poor, it would be bad to assume "that looks like a field, so it must not be where the performance is bad." --------------------- So let us decide to keep optional (), fix what we can there. Define what is desired of properties, but for now get rid of what we currently know as property. Then with a complete proposal, we can say it must meet these goals or it won't exist. Since optional () remain, introducing property again will not break code and we will only deal with broken code now (and there would be some just to fix the current behavior and its disconnect with -property)
Jan 29 2013
On Wednesday, January 30, 2013 05:57:14 Jesse Phillips wrote:It seems at least some members for property feel that currently functions are being annotated with property that shouldn't be.The prime example of that would be save. - Jonathan M Davis
Jan 29 2013
On Wednesday, 30 January 2013 at 05:07:15 UTC, Jonathan M Davis wrote:On Wednesday, January 30, 2013 05:57:14 Jesse Phillips wrote:rehash, dup, length (as a setter), the list goes on and on.It seems at least some members for property feel that currently functions are being annotated with property that shouldn't be.The prime example of that would be save. - Jonathan M Davis
Jan 29 2013
On Wednesday, 30 January 2013 at 04:57:15 UTC, Jesse Phillips wrote:I don't agree with the argument that properties provide a convince to identify low overhead access. While I'm not experienced in this area, profile code should indicate where performance is poor, it would be bad to assume "that looks like a field, so it must not be where the performance is bad."Yes, this is true, like always. Even when property isn't involved. Fectching memory that isn't in cache anymore is typically 200-250 CPU cycles on modern x86 architecture. Getting that from a register is immediate. Accessing a variable has unknown cost, and only profile can reveal the truth here. Considering that property/function have some importance in regard of performance is in complete contradiction with how computer and code actually work now. The difference is semantic. In case of property, you think data, in case of function, you think action.
Jan 29 2013
On Wed, Jan 30, 2013 at 06:22:05AM +0100, deadalnix wrote:On Wednesday, 30 January 2013 at 04:57:15 UTC, Jesse Phillips wrote:+1. Too many C programmers (including myself) have preconceived notions about what is efficient and what isn't. Unfortunately, we're wrong more often than we'd like to admit. When we actually run the profiler and get real profile data, it often points to hotspots that are far, far away from where we thought they were. We inherited this premature optimization mindset from the CPUs of the 70's and 80's; today's CPUs have far different performance characteristics, and our preconceived notions are mostly all wrong.I don't agree with the argument that properties provide a convince to identify low overhead access. While I'm not experienced in this area, profile code should indicate where performance is poor, it would be bad to assume "that looks like a field, so it must not be where the performance is bad."Yes, this is true, like always. Even when property isn't involved. Fectching memory that isn't in cache anymore is typically 200-250 CPU cycles on modern x86 architecture. Getting that from a register is immediate. Accessing a variable has unknown cost, and only profile can reveal the truth here.Considering that property/function have some importance in regard of performance is in complete contradiction with how computer and code actually work now. The difference is semantic. In case of property, you think data, in case of function, you think action.+1. The voice of reason. T -- I'm still trying to find a pun for "punishment"...
Jan 29 2013
On Wednesday, 30 January 2013 at 05:22:06 UTC, deadalnix wrote:On Wednesday, 30 January 2013 at 04:57:15 UTC, Jesse Phillips wrote:Yes, very good points. We're likely optimizing away for little to no gain most of the time, and maybe even making things worse not better in some cases. --rtI don't agree with the argument that properties provide a convince to identify low overhead access. While I'm not experienced in this area, profile code should indicate where performance is poor, it would be bad to assume "that looks like a field, so it must not be where the performance is bad."Yes, this is true, like always. Even when property isn't involved. Fectching memory that isn't in cache anymore is typically 200-250 CPU cycles on modern x86 architecture. Getting that from a register is immediate. Accessing a variable has unknown cost, and only profile can reveal the truth here. Considering that property/function have some importance in regard of performance is in complete contradiction with how computer and code actually work now. The difference is semantic. In case of property, you think data, in case of function, you think action.
Jan 29 2013
On Tue, 29 Jan 2013 23:57:14 -0500, Jesse Phillips <Jessekphillips+d gmail.com> wrote:Sorry I have to oppose this. It is in no way a compromise as it is completely different from everything suggested. I'm going to take this opportunity to highjack your thread.You are welcome to it! I don't know if there is a thread on this newsgroup about properties that hasn't been hijacked. I should explain that my reasoning behind this is: 1. Walter wants to get rid of property 2. Dispite 4 years of assuming property will be implemented, the old D1-style crap is still in place. 3. I've been using Objective C for the last 10 months, which implements a similar scheme to properties. The compromise is: OK, you want to ditch property? I can live with that as long as we have some way to designate properties. How about this?Can an pro- property members claim that the current behavior is what you want? I believe this answer is no.The answer is no, but only because what we asked for was never implemented. What was ORIGINALLY designed with property (enforcement of parentheses on functions, enforcement against parentheses on properties) is what we wanted.It seems at least some members for property feel that currently functions are being annotated with property that shouldn't be.This is unavoidable. It's like saying I feel some functions are incorrectly named. property has nothing to do with it. There is no "right" answer to whether something should be a property or not, just like there is no "right" name for a function.It also seems those for property aren't fighting optional parens as much? Can we discuss fixing the issues we have with this. I think a good change is to require parens if returning a callable (opposite of Walters suggestion).Yes, if the choice is between having the previous implementation (D1) and optional parentheses with a way to designate properties, I'll choose the latter.If I have my above claims mostly correct, then I'd say property needs to be put back in the drawing board and re-implemented.If you want to replace property, we need a replacement. property still serves a purpose, even in it's currently crippled form.I'd be for removing it from the language and if we decide on what in needs to enforce and should be part of the language, then its implementation is completed in a feature branch and remains out of the language until it meets the needed enforcement and behavior.Fine, but leave property in until you have completed the replacement feature.Granted I'm not concerned if it doesn't ever come back. I believe it has a legitimate role in allowing a change from field to function without harming usage that can not be achieved without an annotation. However it seems we can't achieve this with the combination of features D employs.Ah, your subtle bias shines through ;) The real fact of the matter is, if D never had the "hack" properties it did, I actually wouldn't care. Calling functions instead of setting or getting properties is not that horrible. But writeln = "hi" is horrible.I don't agree with the argument that properties provide a convince to identify low overhead access. While I'm not experienced in this area, profile code should indicate where performance is poor, it would be bad to assume "that looks like a field, so it must not be where the performance is bad."In general, the idea is to implement fields without having to create storage for them. It will never perform as well as a field.--------------------- So let us decide to keep optional (), fix what we can there. Define what is desired of properties, but for now get rid of what we currently know as property. Then with a complete proposal, we can say it must meet these goals or it won't exist. Since optional () remain, introducing property again will not break code and we will only deal with broken code now (and there would be some just to fix the current behavior and its disconnect with -property)In other words, go back to D1 properties. No thanks. -Steve
Jan 30 2013
On Thursday, 31 January 2013 at 01:26:19 UTC, Steven Schveighoffer wrote:The compromise is: OK, you want to ditch property? I can live with that as long as we have some way to designate properties. How about this?It's only natural that a person wants to advocate for his or her own proposal. That having been said, can I interest you in mine? :-) http://forum.dlang.org/thread/kdukid$stg$1 digitalmars.com?page=2#post-yqvrjszzlcpmmuyqyxdz:40forum.dlang.org That a long link. Here's a shorter one if it doesn't work (my experience with these forums is limited, sometimes the line gets truncated wrongly): http://forum.dlang.org/thread/kdukid$stg$1 digitalmars.com?page=2 If it fails to solve any of your problems, perhaps you could tell me how or why. It is necessary to read the whole discussion to get insight on how the proposal is developing. Also note that the top proposal is not directly related to the property discussion, so you have to skip down a few lines to get to the property part.
Jan 30 2013
On Wed, 30 Jan 2013 21:49:35 -0500, Zach the Mystic <reachBUTMINUSTHISzach googlymail.com> wrote:On Thursday, 31 January 2013 at 01:26:19 UTC, Steven Schveighoffer wrote:What you describe is almost exactly something I suggested when the properties but with multiple get/set functions. Can't find it right now, but I found several suggestions of that type. I even found a few that propose exactly what I have! It actually is a bit depressing, we have to reset the clock back to late 2009 to start over with properties... -SteveThe compromise is: OK, you want to ditch property? I can live with that as long as we have some way to designate properties. How about this?It's only natural that a person wants to advocate for his or her own proposal. That having been said, can I interest you in mine? :-) http://forum.dlang.org/thread/kdukid$stg$1 digitalmars.com?page=2#post-yqvrjszzlcpmmuyqyxdz:40forum.dlang.org That a long link. Here's a shorter one if it doesn't work (my experience with these forums is limited, sometimes the line gets truncated wrongly): http://forum.dlang.org/thread/kdukid$stg$1 digitalmars.com?page=2 If it fails to solve any of your problems, perhaps you could tell me how or why. It is necessary to read the whole discussion to get insight on how the proposal is developing. Also note that the top proposal is not directly related to the property discussion, so you have to skip down a few lines to get to the property part.
Jan 31 2013
On 2013-01-31 14:50:40 +0000, "Steven Schveighoffer" <schveiguy yahoo.com> said:It actually is a bit depressing, we have to reset the clock back to late 2009 to start over with properties...I haven't participated in the discussions about properties this time around because it's pretty obvious to me it's getting nowhere. It seems to me that nothing can be done at this point in time if we want to avoid a breakage of almost all current D code. Well, we could make some compromises, but a compromise is going to complicate things while solving only some of the issues; few of us will be really satisfied with such a thing. By the way I was a big proponent of properties with no semantic ambiguities back in 2009. I even proposed a getX/setX scheme, which I still like very much. I'd like to see real properties in D, but I don't think it's realistic at this point. And you have to admit that the way D does properties today is both simple, clever, and appealing. It does have some error-prone liabilities when it comes to callable types and generic programming especially, but beside that I do like the design of the thing. It's a natural extension of UFCS, even though it predates UFCS. Perhaps we should just call it a day and live with the ambiguities. I don't like it, but I don't see any viable alternative. -- Michel Fortin michel.fortin michelf.ca http://michelf.ca/
Jan 31 2013
On Thu, 31 Jan 2013 10:40:18 -0500, Michel Fortin <michel.fortin michelf.ca> wrote:On 2013-01-31 14:50:40 +0000, "Steven Schveighoffer" <schveiguy yahoo.com> said:couldn't find.It actually is a bit depressing, we have to reset the clock back to late 2009 to start over with properties...By the way I was a big proponent of properties with no semantic ambiguities back in 2009. I even proposed a getX/setX scheme, which I still like very much. I'd like to see real properties in D, but I don't think it's realistic at this point.And you have to admit that the way D does properties today is both simple, clever, and appealing. It does have some error-prone liabilities when it comes to callable types and generic programming especially, but beside that I do like the design of the thing. It's a natural extension of UFCS, even though it predates UFCS. Perhaps we should just call it a day and live with the ambiguities. I don't like it, but I don't see any viable alternative.I liked it when I first saw it. Seems, as you say, clever and intuitive. However, it left a bad taste in my mouth when I had a certain situation that I was forced to deal with. In Tango, I developed a struct called TimeSpan, which was a span of time (we have Duration in std.datetime which is similar). I created constructors for spans of time that were named after the units they used. For example, if you wanted a 10 minute, 30 second timespan you could do: auto ts = TimeSpan.minutes(10) + TimeSpan.seconds(30); The idea was to avoid having to document such a line, the above looks obvious. Now, I also had accessors for a given timespan to return the timespan in those units. For example: assert(ts.seconds == 10 * 60 + 30); The problem arose when someone complained that the seconds "setter" wasn't working: ts.seconds = 5; assert(ts.seconds != 5); Wait, what? I never made seconds a settable property! Turns out, this translates to: ts.seconds(5); and because you can call static methods from an instance (another thing I don't really like), it made the constructor act like a property! A completely unintended consequence. The only viable solution (this was D1), was to rename the functions so they couldn't be mistaken as properties. So they all became "fromSeconds" e.g. Yuck! This is one of the reasons I was so excited about D2 getting full-fledged But we never got what was promised, and now we basically have the same junk with some duct-taped garbage keyword that half works. No wonder people don't like property! At this point, I think it would be a huge step backwards not to solve (or at least have a yet-to-be implemented solution for) the above problem. I can live with getters simply being parentheses-less functions, that isn't so bad (though as an API designer, I'd like to have full control over that). But using any function as a setter is crap, and will forever be a wart on D unless we fix it. It will result in bizarre things like mystery setters that don't exist, especially with UFCS. -Steve
Jan 31 2013
On 2013-01-31 15:57:12 +0000, "Steven Schveighoffer" <schveiguy yahoo.com> said:[...] Turns out, this translates to: ts.seconds(5); and because you can call static methods from an instance (another thing I don't really like), it made the constructor act like a property! A completely unintended consequence. The only viable solution (this was D1), was to rename the functions so they couldn't be mistaken as properties. So they all became "fromSeconds" e.g. Yuck!Could also have used global functions instead of static ones inside of the class. I still see your point.At this point, I think it would be a huge step backwards not to solve (or at least have a yet-to-be implemented solution for) the above problem. I can live with getters simply being parentheses-less functions, that isn't so bad (though as an API designer, I'd like to have full control over that). But using any function as a setter is crap, and will forever be a wart on D unless we fix it. It will result in bizarre things like mystery setters that don't exist, especially with UFCS.True. Still, Walter has shown no sign he's willing to accept any solution that won't work with most of current code. Just look at his syntax proposal in the thread "take it behind the woodshed and shoot it?" if you're not convinced. At the same time he has gone to great lengths to keep things backward compatible even with experimental syntaxes (I'm thinking of user defined attributes). I seriously doubt changing the syntax for setters will happen… unless you can make it backward compatible. As for keeping the syntax backward compatible, you could for instance propose an attribute to prevent people from using the setter syntax when calling a particular function: explicit TimeDuration seconds(float); -- Michel Fortin michel.fortin michelf.ca http://michelf.ca/
Jan 31 2013
On Thursday, 31 January 2013 at 15:40:19 UTC, Michel Fortin wrote:And you have to admit that the way D does properties today is both simple, clever, and appealing. It does have some error-prone liabilities when it comes to callable types and generic programming especially, but beside that I do like the design of the thing. It's a natural extension of UFCS, even though it predates UFCS. Perhaps we should just call it a day and live with the ambiguities. I don't like it, but I don't see any viable alternative.I'm hoping that the community won't close the books on this issue without even *examining* my proposal, found here: http://forum.dlang.org/thread/kdukid$stg$1 digitalmars.com?page=2#post-yqvrjszzlcpmmuyqyxdz:40forum.dlang.org If you want the main points, just read all of the posts by Zach the Mystic. I've done my best to defend all criticisms. I simply feel obliged to point out to everyone who wants to shut this issue down that there is another proposal. You may accuse me of being ignorant, or too new to know what I'm saying, but at least try to read the proposal and how the arguments against it have been defended. Or just shut me up by saying something about why it's just wrong or simply can't work.
Jan 31 2013
On Thursday, 31 January 2013 at 19:13:03 UTC, Zach the Mystic wrote: Here's the most concise quote which gives you the gist of the thing: "Now classes are a different kettle of fish. I haven't thought them out and I don't think I need to. They may work seamlessly with my idea or be fraught with problems, I don't know." "But there will never be a need for a new empty struct. The operator new makes no sense. There's no data! Imagine an empty struct as a list of functions under a namespace. That's all it really is. Except it just so happens that this namespace has a bunch of built-in functions which allow it to appear in normal code as if it's a *type*. Want it to appear with parens, so it looks like a function you're calling? Just define opCall inside the struct. Want it to appear before an equals sign. Just define opAssign. As an array? opIndex. A basic type such as an int? opGet. There will never be any need to create an instance. You only need one. At runtime, there is no evidence of a pointer at all, just normal data being passed to normal functions."
Jan 31 2013
On Thu, 31 Jan 2013 14:13:02 -0500, Zach the Mystic <reachBUTMINUSTHISzach googlymail.com> wrote:On Thursday, 31 January 2013 at 15:40:19 UTC, Michel Fortin wrote:been proposed before. Not that there's anything wrong with it, I'm saying it's a duplicate of what has been proposed. If it were to be an acceptable solution, I'd be for familiarity). Don't hold your breath waiting for Walter to respond though, he is notoriously silent unless he completely disagrees with you. -SteveAnd you have to admit that the way D does properties today is both simple, clever, and appealing. It does have some error-prone liabilities when it comes to callable types and generic programming especially, but beside that I do like the design of the thing. It's a natural extension of UFCS, even though it predates UFCS. Perhaps we should just call it a day and live with the ambiguities. I don't like it, but I don't see any viable alternative.I'm hoping that the community won't close the books on this issue without even *examining* my proposal, found here: http://forum.dlang.org/thread/kdukid$stg$1 digitalmars.com?page=2#post-yqvrjszzlcpmmuyqyxdz:40forum.dlang.org
Jan 31 2013
On Thursday, 31 January 2013 at 20:52:39 UTC, Steven Schveighoffer wrote:Thanks for looking at it. didn't find my suggestion to be a duplicate of them. In set? My suggestion allows harnessing the full power of D struct has? My opGet is just another opXXX definable for all structs, not just properties. I had said it was necessary to achieve structs as properties, but I think I was wrong. It's just the equivalent of: int __someRandomFunction() { return _propValue; } alias __someRandomFunction this; But it would be syntactically nicer, much like Highlander structs are syntactically nicer. Therefore, the only language change absolutely required would be making non-static structs nested in structs behave like non-static structs nested in functions, which they arguably should do anyway. Also under the hood, some important optimizations getting rid of pointers for data-less structs. You know, the words "opGet" and "opAssign" (and all the other opXXX's) are rather ugly, but I guess anyone who has defined them in the past could come to love them, for their power if not for their looks.I'm hoping that the community won't close the books on this issue without even *examining* my proposal, found here: http://forum.dlang.org/thread/kdukid$stg$1 digitalmars.com?page=2#post-yqvrjszzlcpmmuyqyxdz:40forum.dlang.orgwhich has been proposed before. Not that there's anything wrong with it, I'm saying it's a duplicate of what has been proposed. If it were to be an acceptable solution, I'd be on board (though I don't know why Don't hold your breath waiting for Walter to respond though, he is notoriously silent unless he completely disagrees with you. -Steve
Jan 31 2013
On Thu, 31 Jan 2013 17:11:28 -0500, Zach the Mystic <reachBUTMINUSTHISzach googlymail.com> wrote:Thanks for looking at it. properties do anything more than just get and set? My suggestion allows harnessing the full power of D struct semantics. Is this not a far moreproperty int foo { get {return _foo;} set {_foo = value;} } Your proposal looks like this: foo struct { int opGet() {return _foo;} void opSet(int value) {_foo = value;} } What I see is that the getter and setter are assigned specific contextual keywords (opGet vs. get, and opSet vs. set). It seems like a very similar (albeit more verbose) solution. What I had originally suggested for properties is this: property int foo { int get() {return _foo;} // only one getter allowed void set(int v) {_foo = v;} void set(float v) {_foo = (int)v;} // more than one setter allowed } I think these are all along the same line of solutions. I don't think they are bad, but clearly they weren't used 4 years ago, so it may be difficult to convince Walter to use them now.My opGet is just another opXXX definable for all structs, not just properties.I didn't see that, but I also don't really see the point of that. What value does opGet have unless it's a getter for a property?I had said it was necessary to achieve structs as properties, but I think I was wrong. It's just the equivalent of: int __someRandomFunction() { return _propValue; } alias __someRandomFunction this; But it would be syntactically nicer, much like Highlander structs are syntactically nicer. Therefore, the only language change absolutely required would be making non-static structs nested in structs behave like non-static structs nested in functions, which they arguably should do anyway. Also under the hood, some important optimizations getting rid of pointers for data-less structs.This is a VERY bad idea. A struct is POD. For example, consider a range type for a container. You may not NEED to have a pointer to the container, so that is wasted bytes. Also note that structs are not meant to have internal pointers. So a "property" struct with an internal pointer The strange case for a struct type inside a function kind of makes sense, because of the ability to access the function's variables, and because you can't really move the stack frame. -Steve
Jan 31 2013
On Thu, 31 Jan 2013 17:54:21 -0500, Steven Schveighoffer <schveiguy yahoo.com> wrote:Also note that structs are not meant to have internal pointers. So a "property" struct with an internal pointerForgot to finish this sentence before I hit send. So a "property" struct with an internal pointer would have to be modified when a copy of the struct is made. But this is bad, structs are supposed to be movable WITHOUT updating anything. -Steve
Jan 31 2013
On Thursday, 31 January 2013 at 23:05:14 UTC, Steven Schveighoffer wrote:On Thu, 31 Jan 2013 17:54:21 -0500, Steven Schveighoffer <schveiguy yahoo.com> wrote:Except when postblit is defined...? Or opAssign?Also note that structs are not meant to have internal pointers. So a "property" struct with an internal pointerForgot to finish this sentence before I hit send. So a "property" struct with an internal pointer would have to be modified when a copy of the struct is made. But this is bad, structs are supposed to be movable WITHOUT updating anything.
Jan 31 2013
On Thu, 31 Jan 2013 18:48:18 -0500, Era Scarecrow <rtcvb32 yahoo.com> wrote:On Thursday, 31 January 2013 at 23:05:14 UTC, Steven Schveighoffer wrote:I'm pretty sure structs are forbidden to have internal pointers. They must be able to be moved without any post-processing. -SteveOn Thu, 31 Jan 2013 17:54:21 -0500, Steven Schveighoffer <schveiguy yahoo.com> wrote:Except when postblit is defined...? Or opAssign?Also note that structs are not meant to have internal pointers. So a "property" struct with an internal pointerForgot to finish this sentence before I hit send. So a "property" struct with an internal pointer would have to be modified when a copy of the struct is made. But this is bad, structs are supposed to be movable WITHOUT updating anything.
Jan 31 2013
On Thursday, 31 January 2013 at 23:57:59 UTC, Steven Schveighoffer wrote:On Thu, 31 Jan 2013 18:48:18 -0500, Era Scarecrow <rtcvb32 yahoo.com> wrote:Hmmm... Well I threw out an idea about not returning inner structs (outside the controlling parent). If that were followed, the reference to the parent could silently be added to the function call rather than the struct itself; Then the data can be moved freely.On Thursday, 31 January 2013 at 23:05:14 UTC, Steven Schveighoffer wrote:I'm pretty sure structs are forbidden to have internal pointers. They must be able to be moved without any post-processing.Also note that structs are not meant to have internal pointers. So a "property" struct with an internal pointer So a "property" struct with an internal pointer would have to be modified when a copy of the struct is made. But this is bad, structs are supposed to be movable WITHOUT updating anything.Except when postblit is defined...? Or opAssign?
Jan 31 2013
On Thursday, January 31, 2013 18:58:00 Steven Schveighoffer wrote:I'm pretty sure structs are forbidden to have internal pointers. They must be able to be moved without any post-processing.Structs must be moveable. I believe that you can technically have a struct with a pointer refering to one of its members, but if you do, it will break as soon as your struct is moved (which _will_ happen). - Jonathan M Davis
Jan 31 2013
On Thursday, 31 January 2013 at 22:54:21 UTC, Steven Schveighoffer wrote:property int foo { get {return _foo;} set {_foo = value;} } Your proposal looks like this: foo struct { int opGet() {return _foo;} void opSet(int value) {_foo = value;} } What I see is that the getter and setter are assigned specific contextual keywords (opGet vs. get, and opSet vs. set). It seems like a very similar (albeit more verbose) solution. What I had originally suggested for properties is this: property int foo { int get() {return _foo;} // only one getter allowed void set(int v) {_foo = v;} void set(float v) {_foo = (int)v;} // more than one setter allowed } I think these are all along the same line of solutions. I don't think they are bad, but clearly they weren't used 4 years ago, so it may be difficult to convince Walter to use them now.I think my suggestion goes far beyond what you suspect. It goes way beyond mere getting and setting of variables. Here is basically how you implement a basic int as a property, assuming my new syntax and language adjustments. You need: 1) a struct to have the property in, which is just a normal struct. 2) An actual integer which will be indirectly accessed by using the properties. Let's call it "_n" and the property "n". 3) a struct to hold all of the property functions which access _n. THIS STRUCT CONTAINS NO DATA OF ITS OWN. 4) A bunch of methods implementing all the operators you want. For int, that's quite a lot, so I'll shorten it to a getter, a setter, and an adder. I'll even leave out opGet and use an alias to what might as well be opGet. I'll give the adder a little personality because what's the point of properties if they don't do something different from a basic type? struct myStruct { int _n; n struct { int __mightAsWellBeOpGet() { return _n; } alias __mightAsWellBeOpGet this; int opAssign(int newN) { _n = newN; return _n; } int opBinary(string op) (int rhs) { static if (op == "+") { writeln("You sure are adding a funky int, my friend..."); return _n + rhs; } else static assert(0, "Operator "~op~" not implemented"); } } } This is not some kind of special property implementation. n is a struct. It has no data and therefore is a very peculiar kind of struct. A struct with no data needs only one instance, ever. Copying it is pointless. Taking its address is pointless. Creating a new instance is pointless. Passing it by ref is pointless. All operations which require more than one instance are pointless, which is why it doesn't need a separately defined type. The type and the instance can therefore use the same name, n in this case. Note that n uses the new rule which allows it access to its parent's scope, the same way it would in a nested function. The only pointer it needs is the same pointer used for myStruct, since myStruct actually stores some data. Using the int is as simple as: myStruct foo; foo.n = 4; // Calls opAssign writeln(foo.n); // uses alias this to call __mightAsWellBeOpGet writeln(foo.n + 4); // Calls opBinary. Prints: You sure are adding a funky int, my friend... 8 There's literally nothing these properties can't do that a full-fledged struct type couldn't do.My opGet is just another opXXX definable for all structs, not just properties.I didn't see that, but I also don't really see the point of that. What value does opGet have unless it's a getter for a property?I had said it was necessary to achieve structs as properties, but I think I was wrong. It's just the equivalent of: int __someRandomFunction() { return _propValue; } alias __someRandomFunction this; But it would be syntactically nicer, much like Highlander structs are syntactically nicer. Therefore, the only language change absolutely required would be making non-static structs nested in structs behave like non-static structs nested in functions, which they arguably should do anyway. Also under the hood, some important optimizations getting rid of pointers for data-less structs.This is a VERY bad idea. A struct is POD. For example, consider a range type for a container. You may not NEED to have a pointer to the container, so that is wasted bytes. Also note that structs are not meant to have internal pointers. So a "property" struct with an internal pointer The strange case for a struct type inside a function kind of makes sense, because of the ability to access the function's variables, and because you can't really move the stack frame. -Steve
Jan 31 2013
On Friday, 1 February 2013 at 00:59:47 UTC, Zach the Mystic wrote:writeln(foo.n); // uses alias this to call __mightAsWellBeOpGetNo it won't. It will print "n()". And that exactly (passing to a templated parameter) is the insurmountable problem in using a variable to represent a property.
Jan 31 2013
On Friday, 1 February 2013 at 01:53:05 UTC, TommiT wrote:On Friday, 1 February 2013 at 00:59:47 UTC, Zach the Mystic wrote:On Friday, 1 February 2013 at 01:53:05 UTC, TommiT wrote:writeln(foo.n); // uses alias this to call __mightAsWellBeOpGetNo it won't. It will print "n()". And that exactly (passing to a templated parameter) is the insurmountable problem in using a variable to represent a property.And that exactly (passing to a templated parameter) is the insurmountable problem in using a variable to represent a property.And here's another example of why it is as big of a problem as I make it sound to be: import std.concurrency; struct Array { int _len; length struct // Using Zach's syntax { property get() { return _len; } alias this = get; void opAssign(int rhs) { _len = rhs; } } } void func(T)(T t) { auto v = t; v = 10; } void main() { Array arr; spawn(&func!int, arr.length); arr.length = 20; // And here we have a data-race. // Good luck trying to find these // kinds of bugs. }
Jan 31 2013
On Friday, 1 February 2013 at 02:27:30 UTC, TommiT wrote:[..] as big of a problem as I make it sound to be:...make it out to be...
Jan 31 2013
On Friday, 1 February 2013 at 02:27:30 UTC, TommiT wrote:And here's another example of why it is as big of a problem as I make it sound to be: import std.concurrency; struct Array { int _len; length struct // Using Zach's syntax { property get() { return _len; } alias this = get; void opAssign(int rhs) { _len = rhs; } } } void func(T)(T t) { auto v = t; v = 10; } void main() { Array arr; spawn(&func!int, arr.length); arr.length = 20; // And here we have a data-race. // Good luck trying to find these // kinds of bugs. }I'm sorry, I know very little about race conditions. If you might explain just a little bit about what is happening here, I'd be in a better position to understand what you're saying. I really can't say anything other than please describe what this does and why it's a problem at this time.
Jan 31 2013
On Friday, 1 February 2013 at 03:13:42 UTC, Zach the Mystic wrote:On Friday, 1 February 2013 at 02:27:30 UTC, TommiT wrote:spawn(&func!int, arr.length); ...creates a new thread and runs the following function call in it: func!(int)(arr.length) While that function call is evaluating in the new thread, the old thread may simultaneosly execute: arr.length = 20; Since both of those threads end up at some point calling arr.length.opAssign and therefore both of them may assign to arr._len simultaneously, that's a data-race. It would be data-race also if only one of them wrote to it and the other one just read it.And here's another example of why it is as big of a problem as I make it sound to be: import std.concurrency; struct Array { int _len; length struct // Using Zach's syntax { property get() { return _len; } alias this = get; void opAssign(int rhs) { _len = rhs; } } } void func(T)(T t) { auto v = t; v = 10; } void main() { Array arr; spawn(&func!int, arr.length); arr.length = 20; // And here we have a data-race. // Good luck trying to find these // kinds of bugs. }I'm sorry, I know very little about race conditions. If you might explain just a little bit about what is happening here, I'd be in a better position to understand what you're saying. I really can't say anything other than please describe what this does and why it's a problem at this time.
Jan 31 2013
On Friday, 1 February 2013 at 03:39:19 UTC, TommiT wrote:On Friday, 1 February 2013 at 03:13:42 UTC, Zach the Mystic wrote:I'm familiar with the fact that programmers face endless woes with regard to data-races. I thought that D has unshared data by default. But since Array arr is defined in main instead of outside main, therefore it is sharable between the two threads? If two threads have access to the same data, what makes length as a property different from length as an int? This problem may be over my head for now...On Friday, 1 February 2013 at 02:27:30 UTC, TommiT wrote:spawn(&func!int, arr.length); ...creates a new thread and runs the following function call in it: func!(int)(arr.length) While that function call is evaluating in the new thread, the old thread may simultaneosly execute: arr.length = 20; Since both of those threads end up at some point calling arr.length.opAssign and therefore both of them may assign to arr._len simultaneously, that's a data-race. It would be data-race also if only one of them wrote to it and the other one just read it.And here's another example of why it is as big of a problem as I make it sound to be: import std.concurrency; struct Array { int _len; length struct // Using Zach's syntax { property get() { return _len; } alias this = get; void opAssign(int rhs) { _len = rhs; } } } void func(T)(T t) { auto v = t; v = 10; } void main() { Array arr; spawn(&func!int, arr.length); arr.length = 20; // And here we have a data-race. // Good luck trying to find these // kinds of bugs. }I'm sorry, I know very little about race conditions. If you might explain just a little bit about what is happening here, I'd be in a better position to understand what you're saying. I really can't say anything other than please describe what this does and why it's a problem at this time.
Jan 31 2013
On Friday, 1 February 2013 at 04:22:51 UTC, Zach the Mystic wrote:On Friday, 1 February 2013 at 03:39:19 UTC, TommiT wrote:Actually, that example of mine was wrong - it's not a data-race. I failed to notice that in: spawn(&func!int, arr.length); ...arr.length is actually converted to int using alias this. My bad. Now I'm going to repeat the "spooky modification at a distance" problem I showed earlier, but this time, instead of writing it in the new syntax and the new struct behaviour you invented, I write it using current D syntax: import std.concurrency; struct Array { int _len; struct PropType { Array* _outer; // In your syntax this was implicit property int get() { return _outer._len; } alias this = get; void opAssign(int rhs) { _outer._len = rhs; } } PropType length; } void func(T)(T t) if (isImplicitlyConvertible!(T,int)) { // Given that is(T == Array.PropType), then // all 3 lines below do the same thing: t = 42; t.opAssign(42); t._outer._len = 42; } void main() { Array arr; // setting the _outer pointer to the enclosing object: arr.length._outer = &arr; assert(arr._len == 0); func(arr.length); // no conversion to int happening here assert(arr._len == 42); } So, it's possible to modify arr._len just by passing arr.length by value to a function.On Friday, 1 February 2013 at 03:13:42 UTC, Zach the Mystic wrote:I'm familiar with the fact that programmers face endless woes with regard to data-races. I thought that D has unshared data by default. But since Array arr is defined in main instead of outside main, therefore it is sharable between the two threads? If two threads have access to the same data, what makes length as a property different from length as an int? This problem may be over my head for now...On Friday, 1 February 2013 at 02:27:30 UTC, TommiT wrote:spawn(&func!int, arr.length); ...creates a new thread and runs the following function call in it: func!(int)(arr.length) While that function call is evaluating in the new thread, the old thread may simultaneosly execute: arr.length = 20; Since both of those threads end up at some point calling arr.length.opAssign and therefore both of them may assign to arr._len simultaneously, that's a data-race. It would be data-race also if only one of them wrote to it and the other one just read it.And here's another example of why it is as big of a problem as I make it sound to be: import std.concurrency; struct Array { int _len; length struct // Using Zach's syntax { property get() { return _len; } alias this = get; void opAssign(int rhs) { _len = rhs; } } } void func(T)(T t) { auto v = t; v = 10; } void main() { Array arr; spawn(&func!int, arr.length); arr.length = 20; // And here we have a data-race. // Good luck trying to find these // kinds of bugs. }I'm sorry, I know very little about race conditions. If you might explain just a little bit about what is happening here, I'd be in a better position to understand what you're saying. I really can't say anything other than please describe what this does and why it's a problem at this time.
Feb 01 2013
On Friday, 1 February 2013 at 01:53:05 UTC, TommiT wrote:On Friday, 1 February 2013 at 00:59:47 UTC, Zach the Mystic wrote:I need to study this principle a little more. In other words, alias this is a templated parameter in this case? Which page is the documentation for these templated parameters, because I didn't see templates in my code.writeln(foo.n); // uses alias this to call __mightAsWellBeOpGetNo it won't. It will print "n()". And that exactly (passing to a templated parameter) is the insurmountable problem in using a variable to represent a property.
Jan 31 2013
On Friday, 1 February 2013 at 02:52:42 UTC, Zach the Mystic wrote:I need to study this principle a little more. In other words, alias this is a templated parameter in this case? Which page is the documentation for these templated parameters, because I didn't see templates in my code.No, alias this is basically implicit cast operator that will be tried if everything else fails. But writeln is a function template, i.e. its parameters/arguments are templated. http://dlang.org/template.html
Jan 31 2013
On Friday, 1 February 2013 at 03:12:29 UTC, TommiT wrote:On Friday, 1 February 2013 at 02:52:42 UTC, Zach the Mystic wrote:If what you say is true, then all the more reason to build opGet into the compiler... Was I correct in saying that the template in question was to!string(foo.n)? Or does the problem occur in passing to writeln() itself?I need to study this principle a little more. In other words, alias this is a templated parameter in this case? Which page is the documentation for these templated parameters, because I didn't see templates in my code.No, alias this is basically implicit cast operator that will be tried if everything else fails. But writeln is a function template, i.e. its parameters/arguments are templated. http://dlang.org/template.html
Jan 31 2013
On Friday, 1 February 2013 at 01:53:05 UTC, TommiT wrote:On Friday, 1 February 2013 at 00:59:47 UTC, Zach the Mystic wrote:to!string(foo.n)... hmmm... not that I know how to solve it right away, but is it possible to do: alias template theFuncIActuallyWant this; int theFuncIActuallyWant() { return 1; } ...in order to have it pass the right thing to the template parameter? That's just a jury rigged syntax which might help structs make more sense to the compiler when passed through templates. You say it's insurmountable, and I don't know enough about the details to know, but it seems like surely SOMETHING could be done to get the right result without messing up everything else in the process.writeln(foo.n); // uses alias this to call __mightAsWellBeOpGetNo it won't. It will print "n()". And that exactly (passing to a templated parameter) is the insurmountable problem in using a variable to represent a property.
Jan 31 2013
On Friday, 1 February 2013 at 03:08:12 UTC, Zach the Mystic wrote:On Friday, 1 February 2013 at 01:53:05 UTC, TommiT wrote:I think this is taken care of actually, with opCast(string). The docs for std.conv.to with opCast may contain a typo: "toImpl(T, S)(S value); When source type supports member template function opCast, is is used." I think it might mean "it is used" since I don't know why it would use "is" instead of the opCast. If that's true, just override opCast(string), no? Still, it would be great to be able to "prefer" a particular alias this when passed to templates.On Friday, 1 February 2013 at 00:59:47 UTC, Zach the Mystic wrote:to!string(foo.n)... hmmm...writeln(foo.n); // uses alias this to call __mightAsWellBeOpGetNo it won't. It will print "n()". And that exactly (passing to a templated parameter) is the insurmountable problem in using a variable to represent a property.
Jan 31 2013
On Friday, 1 February 2013 at 03:23:09 UTC, Zach the Mystic wrote:I think it might mean "it is used" since I don't know why it would use "is" instead of the opCast. If that's true, just override opCast(string), no?Yes, there's probably a way to pass to writeln by providing opCast(string). But we're not talking only about writeln here, we're talking about all function templates being a potential problem.
Jan 31 2013
On Friday, 1 February 2013 at 03:44:51 UTC, TommiT wrote:On Friday, 1 February 2013 at 03:23:09 UTC, Zach the Mystic wrote:Not really sure what you mean. I have a bunch of thoughts, but my overall knowledge of these things is too little, I'm afraid. If you're interested, I'd like an example of how the templates will be so much of a problem, illustrating the collision between the two core language features in question.I think it might mean "it is used" since I don't know why it would use "is" instead of the opCast. If that's true, just override opCast(string), no?Yes, there's probably a way to pass to writeln by providing opCast(string). But we're not talking only about writeln here, we're talking about all function templates being a potential problem.
Jan 31 2013
On Friday, 1 February 2013 at 03:08:12 UTC, Zach the Mystic wrote:alias template theFuncIActuallyWant this; int theFuncIActuallyWant() { return 1; } ...in order to have it pass the right thing to the template parameter? That's just a jury rigged syntax which might help structs make more sense to the compiler when passed through templates.None of the alias this conversions are even looked at when you pass a variable to a templated parameter. The template simply conforms to whatever type the passed variable is. No conversions ever happen. That's just how templates work in D. I can't right off the bat say that it's impossible to design a language where templates perform conversions. But it's safe to say that it's not happening with this language. It would be a huge change.
Jan 31 2013
On Friday, 1 February 2013 at 03:28:05 UTC, TommiT wrote:On Friday, 1 February 2013 at 03:08:12 UTC, Zach the Mystic wrote:What I meant to suggest was an actual new feature which would allow one preferred argument to be passed to a template.alias template theFuncIActuallyWant this; int theFuncIActuallyWant() { return 1; } ...in order to have it pass the right thing to the template parameter? That's just a jury rigged syntax which might help structs make more sense to the compiler when passed through templates.None of the alias this conversions are even looked at when you pass a variable to a templated parameter. The template simply conforms to whatever type the passed variable is. No conversions ever happen. That's just how templates work in D. I can't right off the bat say that it's impossible to design a language where templates perform conversions. But it's safe to say that it's not happening with this language. It would be a huge change.
Jan 31 2013
On Friday, 1 February 2013 at 03:33:05 UTC, Zach the Mystic wrote:On Friday, 1 February 2013 at 03:28:05 UTC, TommiT wrote:Frankly, it was your use of the word "insurmountable" which rubbed me the wrong way, but I reach the limits of my awareness at this point.On Friday, 1 February 2013 at 03:08:12 UTC, Zach the Mystic wrote:What I meant to suggest was an actual new feature which would allow one preferred argument to be passed to a template.alias template theFuncIActuallyWant this; int theFuncIActuallyWant() { return 1; } ...in order to have it pass the right thing to the template parameter? That's just a jury rigged syntax which might help structs make more sense to the compiler when passed through templates.None of the alias this conversions are even looked at when you pass a variable to a templated parameter. The template simply conforms to whatever type the passed variable is. No conversions ever happen. That's just how templates work in D. I can't right off the bat say that it's impossible to design a language where templates perform conversions. But it's safe to say that it's not happening with this language. It would be a huge change.
Jan 31 2013
On Thu, 31 Jan 2013 19:59:46 -0500, Zach the Mystic <reachBUTMINUSTHISzach googlymail.com> wrote:I think my suggestion goes far beyond what you suspect. It goes way beyond mere getting and setting of variables. Here is basically how you implement a basic int as a property, assuming my new syntax and language adjustments. You need: 1) a struct to have the property in, which is just a normal struct. 2) An actual integer which will be indirectly accessed by using the properties. Let's call it "_n" and the property "n". 3) a struct to hold all of the property functions which access _n. THIS STRUCT CONTAINS NO DATA OF ITS OWN. 4) A bunch of methods implementing all the operators you want. For int, that's quite a lot, so I'll shorten it to a getter, a setter, and an adder. I'll even leave out opGet and use an alias to what might as well be opGet. I'll give the adder a little personality because what's the point of properties if they don't do something different from a basic type? struct myStruct { int _n; n struct { int __mightAsWellBeOpGet() { return _n; } alias __mightAsWellBeOpGet this; int opAssign(int newN) { _n = newN; return _n; } int opBinary(string op) (int rhs) { static if (op == "+") { writeln("You sure are adding a funky int, my friend..."); return _n + rhs; } else static assert(0, "Operator "~op~" not implemented"); } } } This is not some kind of special property implementation. n is a struct. It has no data and therefore is a very peculiar kind of struct. A struct with no data needs only one instance, ever. Copying it is pointless. Taking its address is pointless. Creating a new instance is pointless. Passing it by ref is pointless. All operations which require more than one instance are pointless, which is why it doesn't need a separately defined type. The type and the instance can therefore use the same name, n in this case.No, the struct must have data. If it doesn't, how does it get back to the owner type? In other words, your n struct must have a pointer to the myStruct instance it intends to modify _n on. Unless, of course, you pass the pointer to myStruct as the 'this' reference. But then, this isn't a normal struct, and I'm really failing to see why we have to make this a struct at all.Note that n uses the new rule which allows it access to its parent's scope, the same way it would in a nested function. The only pointer it needs is the same pointer used for myStruct, since myStruct actually stores some data.FYI, nested structs in functions (the ones you want to use as a model) have an extra hidden reference pointer back to the stack frame data. That is how they can access the local variables of the function. This proposal looks way too complicated. I don't see how it's a win over the current state of affairs, or even the property implementation we expected to get but didn't. You need to solve the "owner pointer" problem before it's even viable. -Steve
Jan 31 2013
On Friday, 1 February 2013 at 04:33:05 UTC, Steven Schveighoffer wrote:On Thu, 31 Jan 2013 19:59:46 -0500, Zach the Mystic:How does any function get hooked up with data? The compiler figures out what data is to be passed to which function. It's no different from how the compiler figures out how to pass data defined in one module to functions defined in a different module. Empty structs are just namespaces with powerful semantics. They have no pointers, unless they're nested in a struct with data, in which case they have the same pointer as any member function of that struct. struct A { int q = 23; void incrementQ() { ++q; } } How on earth could this function increment q when it's not even defined in the function?!?!? It must be a miracle. Oh, no wait, it needs a pointer to the struct in question. Duh. There's no difference with data-less structs inside regular structs. struct A { int q; incrementQ struct { void opCall() { ++q; } } } Where's the need for some hocus-pocus mystery pointer here? The empty struct has no data to worry about. Functions inside the empty struct get the same damn pointer as the other functions in struct A. But of course, you can't do this: struct B { int _q; q struct { int opUnary(string s)() if (s == "++") { writeln("You know, I just wanted to have a conversation while I was busy incrementing q"); ++_q; writeln("I did all sorts of stuff with the increment operator while I was at it"); return _q; } } } ...with normal function calls.This is not some kind of special property implementation. n is a struct. It has no data and therefore is a very peculiar kind of struct. A struct with no data needs only one instance, ever. Copying it is pointless. Taking its address is pointless. Creating a new instance is pointless. Passing it by ref is pointless. All operations which require more than one instance are pointless, which is why it doesn't need a separately defined type. The type and the instance can therefore use the same name, n in this case.No, the struct must have data. If it doesn't, how does it get back to the owner type? In other words, your n struct must have a pointer to the myStruct instance it intends to modify _n on.Unless, of course, you pass the pointer to myStruct as the 'this' reference.Ain't no "this" in an empty struct. Use "outer.this" instead.But then, this isn't a normal struct, and I'm really failing to see why we have to make this a struct at all.Because it's already implemented, except for a few details, because it opens up possibilities for properties other languages could only dream of, and because it obviates the need for tags like property to provide far weaker functionality.Yeah, see, the problem is, if empty structs, which require no "this" pointer to themselves, are allowed access to their parent scope, it suggests that all structs should do the same. Now we have one good syntax for these things : "foo struct { ... }", which could be fun to use in other places too (where you want a single instance of a struct). But if these empty structs are fundamentally different from regular structs, it will force a situation where the Highlander syntax must be used only on these "special" structs, to make sure the compiler knows the difference. It's a problem, to be sure.Note that n uses the new rule which allows it access to its parent's scope, the same way it would in a nested function. The only pointer it needs is the same pointer used for myStruct, since myStruct actually stores some data.FYI, nested structs in functions (the ones you want to use as a model) have an extra hidden reference pointer back to the stack frame data. That is how they can access the local variables of the function.This proposal looks way too complicated. I don't see how it's a win over the current state of affairs, or even the property implementation we expected to get but didn't. You need to solve the "owner pointer" problem before it's even viable. -SteveYou say it's complicated, but I ask you this: does any other proposal completely eliminate the so-called eye-sore " property" while also providing functionality with unknown potential which goes far beyond what people are used to? And the owner pointer problem is only a problem if we want to make the language complete and consistent with regard to normal non-static structs holding an outer struct pointer. I think having a use case for this type of struct would seal the deal, but as it is, I'm not sure.
Jan 31 2013
On Friday, 1 February 2013 at 06:52:32 UTC, Zach the Mystic wrote:What I mean is, that the annoying aspect of making struct-nested structs act like their function-nested struct counterparts is that the part which is most difficult to implement will actually be the part people use the least. The main need is for data-less struct-nested structs to have access to their parent's scope, but implementing struct-nested structs which actually hold data will be more annoying, but it will be necessary for language consistency. But I though of a rather crude temporary fix. Simply disallow non-static struct-nested structs which actually hold data of their own. With this error built-in, all programmers can now tag all of their struct-nested structs with "static" until their program compiles once more. Now the language is clean and ready for the rather easy addition of data-less nested structs, and the slightly trickier data-ful struct-nested structs to be implemented when the developers get the chance. All structs now will behave the same way, freeing up the Highlander syntax for use on *any* struct, data-less or data-ful.FYI, nested structs in functions (the ones you want to use as a model) have an extra hidden reference pointer back to the stack frame data. That is how they can access the local variables of the function.Yeah, see, the problem is, if empty structs, which require no "this" pointer to themselves, are allowed access to their parent scope, it suggests that all structs should do the same. Now we have one good syntax for these things : "foo struct { ... }", which could be fun to use in other places too (where you want a single instance of a struct). But if these empty structs are fundamentally different from regular structs, it will force a situation where the Highlander syntax must be used only on these "special" structs, to make sure the compiler knows the difference. It's a problem, to be sure.
Feb 01 2013
On Fri, 01 Feb 2013 01:52:29 -0500, Zach the Mystic <reachBUTMINUSTHISzach googlymail.com> wrote:On Friday, 1 February 2013 at 04:33:05 UTC, Steven Schveighoffer wrote:No need to get snippy :) Especially when you are wrong. Try this: struct A { int q; struct B { void foo() {q++;} } } Won't compile. That's becuase foo is passed a reference to the A.B struct, not the A struct. If you want it to compile, B will *necessarily* have to have a pointer to A. If you want B's methods to be passed A's pointer, then this is not a struct. Plain and simple. It's just a namespace, the "just like any other struct" is meaningless, since it isn't. Now, try this: struct S {} pragma(msg, sizeof(S).stringof); // outputs 1 (empty structs must have some size). void foo() { int q; struct A { void foo() {q++;} } pragma(msg, sizeof(A).stringof); // outputs 4 (or 8 on 64-bit machines) } Why? Because the reason those "miracle" nested structs work is because they have a hidden context pointer. Even empty structs have size of 1 byte because they must have a 'this' pointer.No, the struct must have data. If it doesn't, how does it get back to the owner type? In other words, your n struct must have a pointer to the myStruct instance it intends to modify _n on.How does any function get hooked up with data? The compiler figures out what data is to be passed to which function. It's no different from how the compiler figures out how to pass data defined in one module to functions defined in a different module. Empty structs are just namespaces with powerful semantics. They have no pointers, unless they're nested in a struct with data, in which case they have the same pointer as any member function of that struct. struct A { int q = 23; void incrementQ() { ++q; } } How on earth could this function increment q when it's not even defined in the function?!?!? It must be a miracle. Oh, no wait, it needs a pointer to the struct in question. Duh.There's no difference with data-less structs inside regular structs. struct A { int q; incrementQ struct { void opCall() { ++q; } } } Where's the need for some hocus-pocus mystery pointer here? The empty struct has no data to worry about. Functions inside the empty struct get the same damn pointer as the other functions in struct A.Then this is not a normal struct, in fact it has nothing to do with a struct.But of course, you can't do this: struct B { int _q; q struct { int opUnary(string s)() if (s == "++") { writeln("You know, I just wanted to have a conversation while I was busy incrementing q"); ++_q; writeln("I did all sorts of stuff with the increment operator while I was at it"); return _q; } } } ...with normal function calls.Certainly you can: struct B { int _q; property auto q() { static struct incrementer { int *_q; int opUnary(string s)() if (s == "++") { writeln("You know, I just wanted to have a conversation while I was busy incrementing q"); ++(*_q); writeln("I did all sorts of stuff with the increment operator while I was at it"); return *_q; } } return incrementer(&_q); } } Although, because of dumb rvalue/lvalue rules (apparently, incrementer is not an lvalue, so can't have ++ called on it), this doesn't actually compile... Through some finagling, I can get this to compile, but it's not usable with this compiler bug: import std.stdio; struct B { int _q; struct incrementer { int *_q; int opUnary(string s)() if (s == "++") { writeln("You know, I just wanted to have a conversation while I was busy incrementing q"); ++(*_q); writeln("I did all sorts of stuff with the increment operator while I was at it"); return *_q; } } private incrementer qinc; // needed to make incrementer an lvalue. property ref incrementer q() { qinc._q = &_q; return qinc; } } void main() { B b; assert(b._q == 0); ++b.q; // b.q++ doesn't work, another bug assert(b._q == 1); } it would be useful to be able to define all the operators. So that part of the plan has merit. I think you need to drop the struct moniker. This is not a struct. You do that, and I think your proposal is on more solid ground.outer is the pointer I am referring to. It's not magic, it must come from somewhere. If the struct has no this pointer, it's not a struct. A data-less struct *STILL* has a this pointer.Unless, of course, you pass the pointer to myStruct as the 'this' reference.Ain't no "this" in an empty struct. Use "outer.this" instead.Hand waving doesn't solve the problems. The details are important to resolve. What it seems like you have done is hijacked the 'struct' keyword for a property. It isn't a struct, and it doesn't obviate the need for a tag.But then, this isn't a normal struct, and I'm really failing to see why we have to make this a struct at all.Because it's already implemented, except for a few details, because it opens up possibilities for properties other languages could only dream of, and because it obviates the need for tags like property to provide far weaker functionality.You say it's complicated, but I ask you this: does any other proposal completely eliminate the so-called eye-sore " property" while also providing functionality with unknown potential which goes far beyond what people are used to? And the owner pointer problem is only a problem if we want to make the language complete and consistent with regard to normal non-static structs holding an outer struct pointer. I think having a use case for this type of struct would seal the deal, but as it is, I'm not sure.What I mean by complicated is that it seems like a lot more work than it should be. If we want to define new syntax to define properties, let's do it in a way that is concise and to the point. I don't want to make properties look like structs, they are not structs. -Steve
Feb 01 2013
On Friday, 1 February 2013 at 15:29:38 UTC, Steven Schveighoffer wrote:On Fri, 01 Feb 2013 01:52:29 -0500, Zach the Mystic <reachBUTMINUSTHISzach googlymail.com> wrote:Okay, so you're drawing the line where you think it ends. I want to point out again that my idea requires the language change which allows struct-nested structs access to their parent's scope. The temporary fix is to make it an error to have a non-static struct-nested struct which actually holds data. All programmers can quickly see what's wrong with their code, because they will have to add "static" to data-containing struct-nested structs to get them to compile. As I said above, this is arguably the behavior which should have been implemented in the first place - I'm actually making the language *more* consistent by insisting on this. And there is simply no need for a data-less struct to allow a "this" pointer. There will never be any need to know the address of a data-less struct. Any use of it will simply give: "Error: a struct with no data may not contain a 'this' pointer". And any use requiring taking its address is statically disallowed at compile time. This is not a hard feature to implement.On Friday, 1 February 2013 at 04:33:05 UTC, Steven Schveighoffer wrote:No need to get snippy :) Especially when you are wrong. Try this: struct A { int q; struct B { void foo() {q++;} } } Won't compile. That's becuase foo is passed a reference to the A.B struct, not the A struct. If you want it to compile, B will *necessarily* have to have a pointer to A. If you want B's methods to be passed A's pointer, then this is not a struct. Plain and simple. It's just a namespace, the "just like any other struct" is meaningless, since it isn't. Now, try this: struct S {} pragma(msg, sizeof(S).stringof); // outputs 1 (empty structs must have some size). void foo() { int q; struct A { void foo() {q++;} } pragma(msg, sizeof(A).stringof); // outputs 4 (or 8 on 64-bit machines) } Why? Because the reason those "miracle" nested structs work is because they have a hidden context pointer. Even empty structs have size of 1 byte because they must have a 'this' pointer.No, the struct must have data. If it doesn't, how does it get back to the owner type? In other words, your n struct must have a pointer to the myStruct instance it intends to modify _n on.How does any function get hooked up with data? The compiler figures out what data is to be passed to which function. It's no different from how the compiler figures out how to pass data defined in one module to functions defined in a different module. Empty structs are just namespaces with powerful semantics. They have no pointers, unless they're nested in a struct with data, in which case they have the same pointer as any member function of that struct. struct A { int q = 23; void incrementQ() { ++q; } } How on earth could this function increment q when it's not even defined in the function?!?!? It must be a miracle. Oh, no wait, it needs a pointer to the struct in question. Duh.There's no difference with data-less structs inside regular structs. struct A { int q; incrementQ struct { void opCall() { ++q; } } } Where's the need for some hocus-pocus mystery pointer here? The empty struct has no data to worry about. Functions inside the empty struct get the same damn pointer as the other functions in struct A.Then this is not a normal struct, in fact it has nothing to do with a struct.But of course, you can't do this: struct B { int _q; q struct { int opUnary(string s)() if (s == "++") { writeln("You know, I just wanted to have a conversation while I was busy incrementing q"); ++_q; writeln("I did all sorts of stuff with the increment operator while I was at it"); return _q; } } } ...with normal function calls.Certainly you can: struct B { int _q; property auto q() { static struct incrementer { int *_q; int opUnary(string s)() if (s == "++") { writeln("You know, I just wanted to have a conversation while I was busy incrementing q"); ++(*_q); writeln("I did all sorts of stuff with the increment operator while I was at it"); return *_q; } } return incrementer(&_q); } } Although, because of dumb rvalue/lvalue rules (apparently, incrementer is not an lvalue, so can't have ++ called on it), this doesn't actually compile... Through some finagling, I can get this to compile, but it's not usable with this compiler bug: import std.stdio; struct B { int _q; struct incrementer { int *_q; int opUnary(string s)() if (s == "++") { writeln("You know, I just wanted to have a conversation while I was busy incrementing q"); ++(*_q); writeln("I did all sorts of stuff with the increment operator while I was at it"); return *_q; } } private incrementer qinc; // needed to make incrementer an lvalue. property ref incrementer q() { qinc._q = &_q; return qinc; } } void main() { B b; assert(b._q == 0); ++b.q; // b.q++ doesn't work, another bug assert(b._q == 1); } But I think actually, if we are going to define get and set in operators. So that part of the plan has merit. I think you need to drop the struct moniker. This is not a struct. You do that, and I think your proposal is on more solid ground.outer is the pointer I am referring to. It's not magic, it must come from somewhere. If the struct has no this pointer, it's not a struct. A data-less struct *STILL* has a this pointer.Unless, of course, you pass the pointer to myStruct as the 'this' reference.Ain't no "this" in an empty struct. Use "outer.this" instead.Hand waving doesn't solve the problems. The details are important to resolve. What it seems like you have done is hijacked the 'struct' keyword for a property. It isn't a struct, and it doesn't obviate the need for a tag.But then, this isn't a normal struct, and I'm really failing to see why we have to make this a struct at all.Because it's already implemented, except for a few details, because it opens up possibilities for properties other languages could only dream of, and because it obviates the need for tags like property to provide far weaker functionality.You say it's complicated, but I ask you this: does any other proposal completely eliminate the so-called eye-sore " property" while also providing functionality with unknown potential which goes far beyond what people are used to? And the owner pointer problem is only a problem if we want to make the language complete and consistent with regard to normal non-static structs holding an outer struct pointer. I think having a use case for this type of struct would seal the deal, but as it is, I'm not sure.What I mean by complicated is that it seems like a lot more work than it should be. If we want to define new syntax to define properties, let's do it in a way that is concise and to the point. I don't want to make properties look like structs, they are not structs. -Steve
Feb 01 2013
On 2013-02-01 15:54:14 +0000, "Zach the Mystic" <reachBUTMINUSTHISzach gOOGLYmail.com> said:And there is simply no need for a data-less struct to allow a "this" pointer. There will never be any need to know the address of a data-less struct. Any use of it will simply give: "Error: a struct with no data may not contain a 'this' pointer". And any use requiring taking its address is statically disallowed at compile time. This is not a hard feature to implement.I think what Steven is saying is that you're distorting the concept of a struct beyond recognition. What you really want/need is just some kind of namespace inside the outer scope. Note that D almost has what you want already if you do it through a template mixin: http://www.digitalmars.com/d/archives/digitalmars/D/properties_using_template_mixins_and_alias_this_87952.html The only thing missing is opGet or an equivalent, and probably a more straightforward syntax. And perhaps someone should check whether the functions can be made virtual too (another requirement that doesn't really belong in a struct). -- Michel Fortin michel.fortin michelf.ca http://michelf.ca/
Feb 01 2013
On Friday, 1 February 2013 at 16:24:53 UTC, Michel Fortin wrote:On 2013-02-01 15:54:14 +0000, "Zach the Mystic" <reachBUTMINUSTHISzach gOOGLYmail.com> said:Yes, this is exactly what I am trying to do, because it's yet another totally badass thing to do. But I'm simply adding it to D's list of such things - CTFE, enums as manifest constants(?), the reuse of keyword static all over the place, strings as immutables. Am I wrong?And there is simply no need for a data-less struct to allow a "this" pointer. There will never be any need to know the address of a data-less struct. Any use of it will simply give: "Error: a struct with no data may not contain a 'this' pointer". And any use requiring taking its address is statically disallowed at compile time. This is not a hard feature to implement.I think what Steven is saying is that you're distorting the concept of a struct beyond recognition.What you really want/need is just some kind of namespace inside the outer scope. Note that D almost has what you want already if you do it through a template mixin: http://www.digitalmars.com/d/archives/digitalmars/D/properties_using_template_mixins_and_alias_this_87952.html The only thing missing is opGet or an equivalent, and probably a more straightforward syntax. And perhaps someone should check whether the functions can be made virtual too (another requirement that doesn't really belong in a struct).That's why it's so weird to see people suggesting so many ideas for property, when this functionality is basically already built into the language. My suggestion already works at module level. Look: import std.traits; Front front; struct Front { ref T opCall(T)(T[] a) if (!isNarrowString!(T[]) && !is(T[] == void[])) { assert(a.length, "Attempting to fetch the front of an empty array of " ~ typeof(a[0]).stringof); return a[0]; } } int main(string[] args) { assert([1,2,3].front == 1); return 0; } It needs three improvements: 1) allow it to work everywhere, not just module level 2) make it look good with a new friendly syntax, which by the way I'm more proud of than any other suggestions I've made here 3) optimize away the unnecessary hidden pointers
Feb 01 2013
On Fri, 01 Feb 2013 12:27:58 -0500, Zach the Mystic <reachBUTMINUSTHISzach googlymail.com> wrote:On Friday, 1 February 2013 at 16:24:53 UTC, Michel Fortin wrote:I think you are wrong in how you assume a struct works, but not in your attempt to implement properties. Struct is just not a key to this formula. Note that many (including myself) consider the overloading of static to be a *detriment*.I think what Steven is saying is that you're distorting the concept of a struct beyond recognition.Yes, this is exactly what I am trying to do, because it's yet another totally badass thing to do. But I'm simply adding it to D's list of such things - CTFE, enums as manifest constants(?), the reuse of keyword static all over the place, strings as immutables. Am I wrong?You are applying struct where none is needed. The current front accomplishes what you have shown except it does not require an actual struct instance (as your code does), and it's far easier to understand and implement than your method. What you are trying to do is establish a *namespace* in which to declare operator overloads. The whole idea that it has to be a struct is incorrect, it does not need a "struct" wrapper. I think you are not understanding how a struct is implemented, and how it's methods are implemented. A struct function without a 'this' reference is a static struct function. Nothing different from a standard function, except it is in the struct *namespace*. I think this is what you really are after, a separate *namespace*. I think *that* idea has merit, and should be examined. Drop the struct, and you are back to the table. -SteveWhat you really want/need is just some kind of namespace inside the outer scope. Note that D almost has what you want already if you do it through a template mixin: http://www.digitalmars.com/d/archives/digitalmars/D/properties_using_template_mixins_and_alias_this_87952.html The only thing missing is opGet or an equivalent, and probably a more straightforward syntax. And perhaps someone should check whether the functions can be made virtual too (another requirement that doesn't really belong in a struct).That's why it's so weird to see people suggesting so many ideas for property, when this functionality is basically already built into the language. My suggestion already works at module level. Look: import std.traits; Front front; struct Front { ref T opCall(T)(T[] a) if (!isNarrowString!(T[]) && !is(T[] == void[])) { assert(a.length, "Attempting to fetch the front of an empty array of " ~ typeof(a[0]).stringof); return a[0]; } } int main(string[] args) { assert([1,2,3].front == 1); return 0; } It needs three improvements: 1) allow it to work everywhere, not just module level 2) make it look good with a new friendly syntax, which by the way I'm more proud of than any other suggestions I've made here 3) optimize away the unnecessary hidden pointers
Feb 01 2013
On Friday, 1 February 2013 at 18:34:01 UTC, Steven Schveighoffer wrote:I think you are wrong in how you assume a struct works, but not in your attempt to implement properties. Struct is just not a key to this formula.I disagree. It is absolutely the fundamental key to this formula.Note that many (including myself) consider the overloading of static to be a *detriment*.I guess there's certainly a matter of taste involved here. Had you suggested another keyword, or what had your preferred suggested syntax looked like?You are applying struct where none is needed. The current front accomplishes what you have shown except it does not require an actual struct instance (as your code does), and it's far easier to understand and implement than your method. What you are trying to do is establish a *namespace* in which to declare operator overloads. The whole idea that it has to be a struct is incorrect, it does not need a "struct" wrapper. I think you are not understanding how a struct is implemented, and how it's methods are implemented. A struct function without a 'this' reference is a static struct function. Nothing different from a standard function, except it is in the struct *namespace*. I think this is what you really are after, a separate *namespace*. I think *that* idea has merit, and should be examined. Drop the struct, and you are back to the table. -SteveI'm sorry we couldn't find common ground here. I can imagine two camps developing, one with your ideas and one with mine. As far as a static struct function, how could it get the pointer to its enclosing struct, which it needs in order operate on the enclosing struct's data?
Feb 01 2013
On Fri, 01 Feb 2013 14:17:00 -0500, Zach the Mystic <reachBUTMINUSTHISzach googlymail.com> wrote:On Friday, 1 February 2013 at 18:34:01 UTC, Steven Schveighoffer wrote:Well, we can disagree, but you still haven't explained why it's fundamental. Other languages have implemented properties just fine without having to specify that they are structs or aggregate types. Until you come up with a compelling reason for structs, I'll stand by my position.I think you are wrong in how you assume a struct works, but not in your attempt to implement properties. Struct is just not a key to this formula.I disagree. It is absolutely the fundamental key to this formula.property. It's already there, already used for properties. property foo { int get(); // or opGet void set(int val); // or opSet opBinary(...) // etc. }Note that many (including myself) consider the overloading of static to be a *detriment*.I guess there's certainly a matter of taste involved here. Had you suggested another keyword, or what had your preferred suggested syntax looked like?I'm sorry we couldn't find common ground here. I can imagine two camps developing, one with your ideas and one with mine. As far as a static struct function, how could it get the pointer to its enclosing struct, which it needs in order operate on the enclosing struct's data?There is NO difference between a static struct function and a normal module-level function, EXCEPT in the namespace. How could it get the pointer to its enclosing struct? It can't. Because a struct TYPE doesn't HAVE an enclosing struct. It could have an enclosing struct TYPE, but that's it. In order to have an instance pointer, it needs to have an instance, and you need to have a non-static struct function. Now, you are proposing that we have these special structs (nested structs) must be labeled static, but are not actually static (their methods require a context pointer), who can never have any fields, and whose methods accept a this pointer is not the pointer to the struct instance, but the instance of the containing type (be it class or struct) they reside in. To say this is "just another struct" is an extremely large stretch. I don't want to come across as mean or condescending, but what you have described could never be considered a struct. Period. If you insist that struct is to be used, you will be bashing your head against a brick wall forever here. Drop the idea that it must be a struct, and you may gain some traction. I'm not saying this because it's my opinion, I'm saying this to prevent you from wasting any more time. I don't really want to waste any more of my time either, if struct is what you insist on, then I will respectfully bow out of the conversation. -Steve
Feb 01 2013
On Friday, 1 February 2013 at 19:59:12 UTC, Steven Schveighoffer wrote:On Fri, 01 Feb 2013 14:17:00 -0500, Zach the Mystic <reachBUTMINUSTHISzach googlymail.com> wrote:Okay, fair.On Friday, 1 February 2013 at 18:34:01 UTC, Steven Schveighoffer wrote:Well, we can disagree, but you still haven't explained why it's fundamental. Other languages have implemented properties just fine without having to specify that they are structs or aggregate types. Until you come up with a compelling reason for structs, I'll stand by my position.I think you are wrong in how you assume a struct works, but not in your attempt to implement properties. Struct is just not a key to this formula.I disagree. It is absolutely the fundamental key to this formula.I'm totally sorry. I had meant that some time ago, static was not used so widely in D, and I'll concede it's a bit bulky, for what it does. I wondered what you wanted then that would look or feel better than having "static" plastered all over the place. Having said that, I admit your syntax for property is pretty good. I think it does the job. Now I have to demonstrate why structs would do the job better.property. It's already there, already used for properties. property foo { int get(); // or opGet void set(int val); // or opSet opBinary(...) // etc. }Note that many (including myself) consider the overloading of static to be a *detriment*.I guess there's certainly a matter of taste involved here. Had you suggested another keyword, or what had your preferred suggested syntax looked like?There is NO difference between a static struct function and a normal module-level function, EXCEPT in the namespace. How could it get the pointer to its enclosing struct? It can't. Because a struct TYPE doesn't HAVE an enclosing struct. It could have an enclosing struct TYPE, but that's it. In order to have an instance pointer, it needs to have an instance, and you need to have a non-static struct function. Now, you are proposing that we have these special structs (nested structs) must be labeled static, but are not actually static (their methods require a context pointer), who can never have any fields, and whose methods accept a this pointer is not the pointer to the struct instance, but the instance of the containing type (be it class or struct) they reside in. To say this is "just another struct" is an extremely large stretch.Okay, I can see the confusion... what need to become static are all *current* nested structs. These new special structs are not labelled static at all, precisely because of how important it is for them to define functions which hold pointers to instances of their parent type, no different at all from how it currently works with structs nested in functions. It's a code breakage I'm talking about here. And thank goodness it's one that's relatively easily handled. All normal structs will now define functions which accept a hidden pointer to their enclosing scope. There will be a small performance penalty, just like when a struct inside a function is not marked static, for programmers who fail to mark their nested structs static when possible. My other posts here and a comment by Era Scarecrow on the other thread are starting to address how this transition might be mitigated: http://forum.dlang.org/thread/kdukid$stg$1 digitalmars.com?page=13I don't want to come across as mean or condescending, but what you have described could never be considered a struct. Period. If you insist that struct is to be used, you will be bashing your head against a brick wall forever here. Drop the idea that it must be a struct, and you may gain some traction. I'm not saying this because it's my opinion, I'm saying this to prevent you from wasting any more time. I don't really want to waste any more of my time either, if struct is what you insist on, then I will respectfully bow out of the conversation. -SteveMaybe we both need some time to think about what has already been said.
Feb 01 2013
On 02/01/2013 08:59 PM, Steven Schveighoffer wrote:... Note that many (including myself) consider the overloading of static to be a *detriment*. ...The modifier actually has a consistent meaning. Is it about overloading as in static if and static assert?... Now, you are proposing that we have these special structs (nested structs) must be labeled static, but are not actually static (their methods require a context pointer), ...This is not what static on an aggregate declaration means in D. A static struct is a struct that does not contain a context pointer as an implicit field. All member structs and aggregate members of structs are implicitly static.
Feb 01 2013
On Friday, 1 February 2013 at 19:59:12 UTC, Steven Schveighoffer wrote:Well, we can disagree, but you still haven't explained why it's fundamental. Other languages have implemented properties just fine without having to specify that they are structs or aggregate types. Until you come up with a compelling reason for structs, I'll stand by my position.Do you mind if I put my arguments in a new thread?
Feb 04 2013
On Monday, 4 February 2013 at 22:46:36 UTC, Zach the Mystic wrote:On Friday, 1 February 2013 at 19:59:12 UTC, Steven Schveighoffer wrote:FYI, I got some feedback from Andrei today in the DIP23 thread ... -------------------- On 2/4/13 1:15 PM, Rob T wrote:Well, we can disagree, but you still haven't explained why it's fundamental. Other languages have implemented properties just fine without having to specify that they are structs or aggregate types. Until you come up with a compelling reason for structs, I'll stand by my position.Do you mind if I put my arguments in a new thread?BTW, I am wondering if the idea of "memberspaces" was considered, and if it was considered, then why was it dropped?An idea that departs considerably from the current status in D has a disadvantage compared to an idea that makes things work within the property framework. Andrei -------------------- See http://forum.dlang.org/post/kepcjq$5fa$1 digitalmars.com --rt
Feb 04 2013
I've had to step away from this for a while, but I want to say that I don't see a problem with the data-less "struct" property idea at all, although calling it a struct is perhaps causing some confusion because real structs tend to host internal data of their own rather than reference it from the outside. The proposed new type of property does not have to host its own internal data, and its member functions can be called just like the hosts member functions. The proposed struct property is really something like a namespace for wrapping data and related functions. It is not a regular struct at all, but it does share some of the features of a struct. It like an improved C++ namespace with smarts. Syntactically, we can allow the property to contain its own data internally, but the data will really belong to the hosted structure (class, struct, or module level). Nothing really new needs to be implemented because there's no special need for storing a "this" pointer, and functions get called in the same way as before. The "this" is the host pointer. We can still refer to an inner and an outter this pointer, but that's really an alias for either the hosts "this" (outter) or the property namespace (inner), both use the same this pointer. If we view the property more like a namespace, then certain things become clear, for example the property by itself is not a movable structure, it's permanently attached to the host class, struct, or module. We can only take addresses of addressable items if they are visible. No, the struct-property will not behave exactly like a variable, and I think that idea is a dead end anyway because it's far too complicated to implement and has questionable value. I agree with Walter, it's needs to be put down so we can move on and come up with a better idea that can work and is really useful. I may intuitively feel this is a great idea, but we will need a few compelling use cases that solve real world problems to make a case for it. --rt
Feb 01 2013
On Friday, 1 February 2013 at 17:23:45 UTC, Rob T wrote:I've had to step away from this for a while, but I want to say that I don't see a problem with the data-less "struct" property idea at all, although calling it a struct is perhaps causing some confusion because real structs tend to host internal data of their own rather than reference it from the outside.Hey, thanks for coming back.The proposed new type of property does not have to host its own internal data, and its member functions can be called just like the hosts member functions. The proposed struct property is really something like a namespace for wrapping data and related functions. It is not a regular struct at all, but it does share some of the features of a struct. It like an improved C++ namespace with smarts. Syntactically, we can allow the property to contain its own data internally, but the data will really belong to the hosted structure (class, struct, or module level).I don't like this because structs don't already work that way. All structs can work in exactly the same way. I'm pretty sure there's no need to treat these specially... except under the hood, where compiler optimizes away the unnecessary pointers in the case of data-free structs.Nothing really new needs to be implemented because there's no special need for storing a "this" pointer, and functions get called in the same way as before. The "this" is the host pointer. We can still refer to an inner and an outter this pointer, but that's really an alias for either the hosts "this" (outter) or the property namespace (inner), both use the same this pointer.The problem with overriding "this" is if you later add data to the struct, it will break any code that already uses "this". "outer" doesn't have this problem at all, and is arguably clearer. Therefore, I think "this" should simply be a compile-time error with a data-free struct.If we view the property more like a namespace, then certain things become clear, for example the property by itself is not a movable structure, it's permanently attached to the host class, struct, or module. We can only take addresses of addressable items if they are visible. No, the struct-property will not behave exactly like a variable, and I think that idea is a dead end anyway because it's far too complicated to implement and has questionable value. I agree with Walter, it's needs to be put down so we can move on and come up with a better idea that can work and is really useful.I don't know, Rob T... Walter's recent article on half-floats shows that you can get a struct instance to look pretty darn close to a variable. Is there anything a variable can do that half-floats can't do? Because if not, we're in the money, dude. This does exactly the same thing, just with data stored outside the struct itself.I may intuitively feel this is a great idea, but we will need a few compelling use cases that solve real world problems to make a case for it. --rtYes, but on the other hand, if you provide all the functionality previously requested, plus a whole lot more, a compelling use case becomes a lot less important. Undiscovered country.
Feb 01 2013
On Friday, 1 February 2013 at 17:43:54 UTC, Zach the Mystic wrote: [...]It's one thing to implement a struct, and another thing to implement nested structs that can refer to the host instance. I know some people want nested structs that can work in that way, but implementation is problematic because when the host struct is moved, then the nested struct has to move along with it and this one reason why we don't have them. I am proposing that we avoid the nesting problem by storing all enclosed data outside in the host instance, but this means that the concept is more like a namespace than a real struct, i.e., it is not movable and cannot be accessed in isolation from the host.Syntactically, we can allow the property to contain its own data internally, but the data will really belong to the hosted structure (class, struct, or module level).I don't like this because structs don't already work that way. All structs can work in exactly the same way. I'm pretty sure there's no need to treat these specially... except under the hood, where compiler optimizes away the unnecessary pointers in the case of data-free structs.The idea here is that we have a property implementation that behaves like a namespace but also has some of the features that structs have. We should not call this thing a struct because it is not a true struct, it's something else entirely, not a namespace and not a struct, but it shares some features with both. If you add data to the namespace-struct, the data is not stored inside the namespace, it only appears that way, it's instead stored with the hosting object instance, be it struct, class, or module, so data storage is like a namespace. The "inner" simply refers to the "this" pointer of the host instance, but limited to the data that was declared inside the namespace, the outter pointer refers to the "this" of the host instance as well, but limited to the hosts data instance only. For modules I don't think there's a this pointer, but that's an implementation detail that can be resolved.Nothing really new needs to be implemented because there's no special need for storing a "this" pointer, and functions get called in the same way as before. The "this" is the host pointer. We can still refer to an inner and an outter this pointer, but that's really an alias for either the hosts "this" (outter) or the property namespace (inner), both use the same this pointer.The problem with overriding "this" is if you later add data to the struct, it will break any code that already uses "this". "outer" doesn't have this problem at all, and is arguably clearer. Therefore, I think "this" should simply be a compile-time error with a data-free struct.The Half-Float implementation is not a nested structure, and trying to implement nested structs is where all of the major difficulties come from.No, the struct-property will not behave exactly like a variable, and I think that idea is a dead end anyway because it's far too complicated to implement and has questionable value. I agree with Walter, it's needs to be put down so we can move on and come up with a better idea that can work and is really useful.I don't know, Rob T... Walter's recent article on half-floats shows that you can get a struct instance to look pretty darn close to a variable. Is there anything a variable can do that half-floats can't do? Because if not, we're in the money, dude. This does exactly the same thing, just with data stored outside the struct itself.I think we can easily replace property already with the namespace proposal, however it will not be the full variable emulation that some people had wanted. I don't think full variable emulation can be done anyway and I've seen admissions that it cannot be done by some of the people who want to see full variable emulation. What we can get however is a much better implementation of the property concept through a new gadget that works like a namepsace with some of the nice features seen with structs. I doubt we'll ever see true nested structs that can reference data in a host structs instance and contain it's own data because it introduces a pointer sync problem when the structs are moved around. At this stage in the discussion, I believe that Steven Schveighoffer is correct that we'll get more traction if we drop the nest struct idea and focus instead on implementing a D version of the C++ namespace, with the improvements that allows things like properties to be implemented. If we can show that there are other uses for the idea, then it adds a lot more credibility to the idea because as it stands, we can get properties right now, but they suck (IMHO anyway). If the proposal is only a marginal improvement over what we have now, then it may not be seen as worth implementing. --rtI may intuitively feel this is a great idea, but we will need a few compelling use cases that solve real world problems to make a case for it. --rtYes, but on the other hand, if you provide all the functionality previously requested, plus a whole lot more, a compelling use case becomes a lot less important. Undiscovered country.
Feb 01 2013
On Friday, 1 February 2013 at 21:33:31 UTC, Rob T wrote:It's one thing to implement a struct, and another thing to implement nested structs that can refer to the host instance. I know some people want nested structs that can work in that way, but implementation is problematic because when the host struct is moved, then the nested struct has to move along with it and this one reason why we don't have them.I am not proposing this and I don't think it's actually necessary. My nested struct is just a tried-and-true struct. So what's the difference? How does it still succeed? Not because it contains any special data or hidden pointers unto itself. Rather, because its *functions* are written to *accept hidden pointers*. That way they can operate on whatever instance of their parent's type gets sent to them. They could be optimized, in theory, to only accept pointers to instances they actually worked on. For example, if a nested member function did nothing but set an integer defined in a struct three nests up, it only need take an instance of that struct, but that's an advanced optimization, not necessary for a basic implementation which would simply pass three pointers to every three-deep nested struct member function. If you want an example, just ask.
Feb 01 2013
On Saturday, 2 February 2013 at 03:14:30 UTC, Zach the Mystic wrote:On Friday, 1 February 2013 at 21:33:31 UTC, Rob T wrote:I mean a code example. But since I'm already here: struct A { int _a = 1; B b; struct B { int _b = 1; C c; struct C { int_c = 1; int myMemberFunction() { return _a + _b + _c; } } } } How does myMemberFunction know about _a and _b? Because its implementation is actually: int myMemberFunction(ref A __a, ref A.B __b, ref A.B.C __c) { return __a._a + __b._b + __c._c; } I do find it frustrating that his kind of thing is necessary to get full compatibility between structs and properties, which would be so elegant. Usage would be: A a; assert(a.b.c.myMemberFunction() == 3); ...which is secretly translated to this: assert(A.B.C.myMemberFunction(a, a.b, a.b.c) == 3);It's one thing to implement a struct, and another thing to implement nested structs that can refer to the host instance. I know some people want nested structs that can work in that way, but implementation is problematic because when the host struct is moved, then the nested struct has to move along with it and this one reason why we don't have them.I am not proposing this and I don't think it's actually necessary. My nested struct is just a tried-and-true struct. So what's the difference? How does it still succeed? Not because it contains any special data or hidden pointers unto itself. Rather, because its *functions* are written to *accept hidden pointers*. That way they can operate on whatever instance of their parent's type gets sent to them. They could be optimized, in theory, to only accept pointers to instances they actually worked on. For example, if a nested member function did nothing but set an integer defined in a struct three nests up, it only need take an instance of that struct, but that's an advanced optimization, not necessary for a basic implementation which would simply pass three pointers to every three-deep nested struct member function. If you want an example, just ask.
Feb 01 2013
On Saturday, 2 February 2013 at 03:50:49 UTC, Zach the Mystic wrote:assert(A.B.C.myMemberFunction(a, a.b, a.b.c) == 3);That wouldn't compile, so you must mean: assert(a.b.c.myMemberFunction(a, a.b, a.b.c) == 3); What do you suppose would happen if I wrote the following? struct A { int _a = 1; B b; struct B { int _b = 1; C c; struct C { int _c = 1; int myMemberFunction() { return _a + _b + _c; } } static int otherFunction() { C cc; return cc.myMemberFunction(); } } } void main() { int i = A.B.otherFunction(); }
Feb 01 2013
On Saturday, 2 February 2013 at 06:04:01 UTC, TommiT wrote:What do you suppose would happen if I wrote the following? struct A {<snip>static int otherFunction() { C cc; return cc.myMemberFunction(); }It would refuse to compile as a static function can't point to an instance/parent. I'm convinced you should not be able to return (or create an instance of) a nested struct outside of it's level of control or ability to reference properly. Had it not been static on the other hand... int otherFunction() cc has the same level as c, so the return would be equal to: _a + _b + cc._c
Feb 01 2013
On Saturday, 2 February 2013 at 06:28:47 UTC, Era Scarecrow wrote:It would refuse to compile as a static function can't point to an instance/parent. I'm convinced you should not be able to return (or create an instance of) a nested struct outside of it's level of control or ability to reference properly.Does my suggested way of doing it not do this?
Feb 02 2013
On Saturday, 2 February 2013 at 06:28:47 UTC, Era Scarecrow wrote:On Saturday, 2 February 2013 at 06:04:01 UTC, TommiT wrote:... well, this function requires being called with instances of A, B, and C, so I believe it would error on that account. The only way to call this deeply nested thing would be with an instance of A, which makes sense, since it operates on a variable contained in A. It would have to look like: A a; int z = a.b.c.myMemberFunction(); ... to work, I believe.What do you suppose would happen if I wrote the following? struct A {<snip>static int otherFunction() { C cc; return cc.myMemberFunction(); }It would refuse to compile as a static function can't point to an instance/parent. I'm convinced you should not be able to return (or create an instance of) a nested struct outside of it's level of control or ability to reference properly. Had it not been static on the other hand... int otherFunction() cc has the same level as c, so the return would be equal to: _a + _b + cc._c
Feb 02 2013
On Saturday, 2 February 2013 at 18:03:32 UTC, Zach the Mystic wrote:On Saturday, 2 February 2013 at 06:28:47 UTC, Era ScarecrowYes, it should be callable that way since it knows where a is at. However I would think a nested struct is more a implementation detail. This brings back training when I was on a database/web development. There were 4 tiers, the DB, the Query level (with all the queries), Logic level, then the GUI level. Now something in this was that each level would be separate and not know about the other. When you think about it, it makes sense since you can swap out one for another. But then I began to notice code that broke that very easily. The GUI level would be doing stuff like: //posted twice, once for html formatting <b>Price: $<?db.getPrices.query("select price from priceTable where x=x")?></b> <b>Price: $<?db.getPrices.query("select price from priceTable where x=x")?></b> Not a very large example, however it ended up that the gui was getting into specifics of variables and function calls in other levels that it shouldn't have known about. In short, nested structs would only be accessible (and passable) inside the struct that made it. Meaning that most likely the methods that work with it, and the struct itself should be private.It would refuse to compile as a static function can't point to an instance/parent. I'm convinced you should not be able to return (or create an instance of) a nested struct outside of it's level of control or ability to reference properly. Had it not been static on the other hand... int otherFunction() cc has the same level as c, so the return would be equal to: _a + _b + cc._c... well, this function requires being called with instances of A, B, and C, so I believe it would error on that account. The only way to call this deeply nested thing would be with an instance of A, which makes sense, since it operates on a variable contained in A. It would have to look like: A a; int z = a.b.c.myMemberFunction(); ... to work, I believe.
Feb 02 2013
On Saturday, 2 February 2013 at 20:30:26 UTC, Era Scarecrow wrote:On Saturday, 2 February 2013 at 18:03:32 UTC, Zach the Mystic wrote:I think this belittles just how important that implementation detail really is. Without a good design, the thing could be prohibitively difficult to implement.On Saturday, 2 February 2013 at 06:28:47 UTC, Era ScarecrowYes, it should be callable that way since it knows where a is at. However I would think a nested struct is more a implementation detail.It would refuse to compile as a static function can't point to an instance/parent. I'm convinced you should not be able to return (or create an instance of) a nested struct outside of it's level of control or ability to reference properly. Had it not been static on the other hand... int otherFunction() cc has the same level as c, so the return would be equal to: _a + _b + cc._c... well, this function requires being called with instances of A, B, and C, so I believe it would error on that account. The only way to call this deeply nested thing would be with an instance of A, which makes sense, since it operates on a variable contained in A. It would have to look like: A a; int z = a.b.c.myMemberFunction(); ... to work, I believe.This brings back training when I was on a database/web development. There were 4 tiers, the DB, the Query level (with all the queries), Logic level, then the GUI level. Now something in this was that each level would be separate and not know about the other. When you think about it, it makes sense since you can swap out one for another. But then I began to notice code that broke that very easily. The GUI level would be doing stuff like: //posted twice, once for html formatting <b>Price: $<?db.getPrices.query("select price from priceTable where x=x")?></b> <b>Price: $<?db.getPrices.query("select price from priceTable where x=x")?></b> Not a very large example, however it ended up that the gui was getting into specifics of variables and function calls in other levels that it shouldn't have known about.From what I understand generally, good encapsulation is a difficult design problem. I don't think you're alone.In short, nested structs would only be accessible (and passable) inside the struct that made it. Meaning that most likely the methods that work with it, and the struct itself should be private.Well, if you want access to a struct from outside, save yourself the time and put it outside to begin with. A nested struct of course is directly related to the entity it finds itself in. My pet metaphor is struct Dog containing struct Tail. It would definitely be illogical to put the Tail outside the Dog. You might as well use the built-in functionality for tagging whatever you want private or public, though. Consider this: software design doesn't end at language design. There's only so much a language can do to encourage good design before it starts to feel like it's strong-arming you into certain arbitrary ways of doing things. Doing this too much is actually *bad* language design.
Feb 02 2013
On Sunday, 3 February 2013 at 02:55:44 UTC, Zach the Mystic wrote:Well, if you want access to a struct from outside, save yourself the time and put it outside to begin with. A nested struct of course is directly related to the entity it finds itself in. My pet metaphor is struct Dog containing struct Tail. It would definitely be illogical to put the Tail outside the Dog.If Tail is an autonomous struct/class, then it totally makes sense to put the definition of Tail outside of dog. This enables you to perhaps use the same Tail in Wolf's and Hyeena's definitions. If, on the other hand, Tail is not an autonomous type, but rather, needs to able to wag the dog, then Tail is really more like a separate logical section within Dog's definition, i.e. a namespace within Dog.
Feb 02 2013
On Sunday, 3 February 2013 at 03:15:57 UTC, TommiT wrote:On Sunday, 3 February 2013 at 02:55:44 UTC, Zach the Mystic wrote:A dog's tail is not an autonomous struct/class. If you ever had a dog you would know that. Also, the dog's tail is no namespace because it contains tail-specific data too.Well, if you want access to a struct from outside, save yourself the time and put it outside to begin with. A nested struct of course is directly related to the entity it finds itself in. My pet metaphor is struct Dog containing struct Tail. It would definitely be illogical to put the Tail outside the Dog.If Tail is an autonomous struct/class, then it totally makes sense to put the definition of Tail outside of dog. This enables you to perhaps use the same Tail in Wolf's and Hyeena's definitions. If, on the other hand, Tail is not an autonomous type, but rather, needs to able to wag the dog, then Tail is really more like a separate logical section within Dog's definition, i.e. a namespace within Dog.
Feb 02 2013
On Sunday, 3 February 2013 at 07:33:52 UTC, Zach the Mystic wrote:On Sunday, 3 February 2013 at 03:15:57 UTC, TommiT wrote:I'm sorry, I'm just getting allergic to the word "namespace", since I don't believe any introduction of a special namespace feature in the language is required. Structs are namespaces - you got me there.On Sunday, 3 February 2013 at 02:55:44 UTC, Zach the Mystic wrote:A dog's tail is not an autonomous struct/class. If you ever had a dog you would know that. Also, the dog's tail is no namespace because it contains tail-specific data too.Well, if you want access to a struct from outside, save yourself the time and put it outside to begin with. A nested struct of course is directly related to the entity it finds itself in. My pet metaphor is struct Dog containing struct Tail. It would definitely be illogical to put the Tail outside the Dog.If Tail is an autonomous struct/class, then it totally makes sense to put the definition of Tail outside of dog. This enables you to perhaps use the same Tail in Wolf's and Hyeena's definitions. If, on the other hand, Tail is not an autonomous type, but rather, needs to able to wag the dog, then Tail is really more like a separate logical section within Dog's definition, i.e. a namespace within Dog.
Feb 02 2013
On Sunday, 3 February 2013 at 02:55:44 UTC, Zach the Mystic wrote:On Saturday, 2 February 2013 at 20:30:26 UTC, Era Scarecrow wrote:Agreed 100%, Although a second (instance of) Dog may want to come about and them sniff tails. That's outside access, but it's still within the limits of the Dogs. In those cases a context pointer could be acceptable as long as it's ensuring the data exists (and can't return it from the function); But overwriting one instance with a different context pointer of another could have very curious side effects depending on design. struct Dog { int id; struct Tail { string colorOf = "Black"; //just data. int getId() { return id; } } Tail tail; void func(ref Dog rhs) { //tail2 retains context pointer to rhs. Tail tail2 = rhs.tail; writeln(tail.getId()); //5 writeln(tail2.getId()); //10 } } Dog dog1 = Dog(5); Dog dog2 = Dog(10); dog2.tail.colorOf = "White"; dog1.func(dog2); //context pointer of d2 thrown away after copy, //unless opAssign declared and does something. dog1.tail = dog2.tail; assert(d1.id == 5); //untouched assert(d1.tail.colorOf == "White"); At which case the tail if it's allowed to be copied should be related but not strictly required to be updated or relied on Dog for behavior. Guess it takes a few rules and experiments to find the right balance of accessibility vs reliability vs flexibility.Yes, it should be callable that way since it knows where a is at. However I would think a nested struct is more a implementation detail.I think this belittles just how important that implementation detail really is. Without a good design, the thing could be prohibitively difficult to implement. From what I understand generally, good encapsulation is a difficult design problem. I don't think you're alone.In short, nested structs would only be accessible (and passable) inside the struct that made it. Meaning that most likely the methods that work with it, and the struct itself should be private.Well, if you want access to a struct from outside, save yourself the time and put it outside to begin with. A nested struct of course is directly related to the entity it finds itself in. My pet metaphor is struct Dog containing struct Tail. It would definitely be illogical to put the Tail outside the Dog.
Feb 02 2013
On Sunday, 3 February 2013 at 03:34:23 UTC, Era Scarecrow wrote:Agreed 100%, Although a second (instance of) Dog may want to come about and them sniff tails. That's outside access, but it's still within the limits of the Dogs. In those cases a context pointer could be acceptable as long as it's ensuring the data exists (and can't return it from the function); But overwriting one instance with a different context pointer of another could have very curious side effects depending on design. struct Dog { int id; struct Tail { string colorOf = "Black"; //just data. int getId() { return id; } } Tail tail; void func(ref Dog rhs) { //tail2 retains context pointer to rhs. Tail tail2 = rhs.tail; writeln(tail.getId()); //5 writeln(tail2.getId()); //10 } }There is a bug in this code and it would not compile. Your getId must receive an instance of Dog. A tail by itself has no dog. The compiler cannot rewrite tail.getId() to someImaginaryDog.tail.getId(). It's easy to think about, once you get used to it. Your getId accesses a variable defined only in its parent struct. The compiler detects this and requires receiving a hidden pointer to (and *only to!*) an instance of the parent. The resulting top-level function is: int getId(ref Dog __d) { return __d.id; } See? It may only access a dog, but it's *defined* in the tail. This is the exact behavior we're looking for, and it's easy to implement and causes no real trouble, as far as I can see.Dog dog1 = Dog(5); Dog dog2 = Dog(10); dog2.tail.colorOf = "White"; dog1.func(dog2); //context pointer of d2 thrown away after copy, //unless opAssign declared and does something. dog1.tail = dog2.tail; assert(d1.id == 5); //untouched assert(d1.tail.colorOf == "White"); At which case the tail if it's allowed to be copied should be related but not strictly required to be updated or relied on Dog for behavior. Guess it takes a few rules and experiments to find the right balance of accessibility vs reliability vs flexibility.With the bug removed, will any of these issues pop up? My guess is no.
Feb 02 2013
On Sunday, 3 February 2013 at 07:26:03 UTC, Zach the Mystic wrote:On Sunday, 3 February 2013 at 03:34:23 UTC, Era Scarecrow wrote:I don't see the bug. Tail is known to be a nested struct so it is required to have it's context (parent) attached, so it supplies it although silently; Therefore tail points to rhs & rhs.tail. This is only valid as long as the reference to rhs exists (or as long as this function exists for sure). Besides the 'id' think more it renamed to 'string dogName', therefore you can tell which tail belongs to which dog, be it sparky or scruffy, etc. In this case the nested struct relies on information from it's parent, but the parent doesn't need information from it's nested structs, allowing it to be correct even if the tail gets changed colors. This can have useful other effects in place like compression, maybe DB management (a text query is replaced by a compiled version of the same thing), etc.struct Dog { int id; struct Tail { string colorOf = "Black"; //just data. int getId() { return id; } } Tail tail; void func(ref Dog rhs) { //tail2 retains context pointer to rhs. Tail tail2 = rhs.tail; writeln(tail.getId()); //5 writeln(tail2.getId()); //10 } }There is a bug in this code and it would not compile. Your getId must receive an instance of Dog. A tail by itself has no dog. The compiler cannot rewrite tail.getId() to someImaginaryDog.tail.getId(). It's easy to think about, once you get used to it. Your getId accesses a variable defined only in its parent struct. The compiler detects this and requires receiving a hidden pointer to (and *only to!*) an instance of the parent. The resulting top-level function is: int getId(ref Dog __d) { return __d.id; } See? It may only access a dog, but it's *defined* in the tail. This is the exact behavior we're looking for, and it's easy to implement and causes no real trouble, as far as I can see.Maybe... I forget what the issues were since I went to sleep.Dog dog1 = Dog(5); Dog dog2 = Dog(10); dog2.tail.colorOf = "White"; dog1.func(dog2); //context pointer of d2 thrown away after copy, //unless opAssign is declared and does something. dog1.tail = dog2.tail; assert(dog1.id == 5); //untouched assert(dog1.tail.colorOf == "White"); At which case the tail if it's allowed to be copied should be related but not strictly required to be updated or relied on Dog for behavior. Guess it takes a few rules and experiments to find the right balance of accessibility vs reliability vs flexibility.With the bug removed, will any of these issues pop up? My guess is no.
Feb 03 2013
On Saturday, 2 February 2013 at 06:04:01 UTC, TommiT wrote:On Saturday, 2 February 2013 at 03:50:49 UTC, Zach the Mystic wrote:You're right. I don't know how the compiler stores the name of the function I meant underneath the hood. But it must such a mechanism for naming A.B.C.myMemberFunction, which is nothing more than a function which takes a pointer, or in this case a few pointers, to instances of the appropriate classes. Non-static member functions generally must take pointers to instances of their types. The only difference between this: struct A { int _a; int getA() { return _a; } } And this: struct A { int _a; } int getA(ref A a) { return a._a; } Is that the compiler does the work of including the hidden pointer automatically in the first case, and also encloses getA into a, I hesitate to say it too loud now... namespace, so that it can't just be reached from anywhere.assert(A.B.C.myMemberFunction(a, a.b, a.b.c) == 3);That wouldn't compile, so you must mean: assert(a.b.c.myMemberFunction(a, a.b, a.b.c) == 3);What do you suppose would happen if I wrote the following? struct A { int _a = 1; B b; struct B { int _b = 1; C c; struct C { int _c = 1; int myMemberFunction() { return _a + _b + _c; } } static int otherFunction() { C cc; return cc.myMemberFunction(); } } } void main() { int i = A.B.otherFunction(); }I was simply using A.B.C.myMemberFunction as a shorthand for whatever name the compiler uses underneath the hood to represent the non-static version of the function.
Feb 02 2013
On Saturday, 2 February 2013 at 17:25:57 UTC, Zach the Mystic wrote:Yes, I can see that now. I didn't understand that the code wasn't actual code but something that the compiler sees. But, you didn't answer my question. What would happen if I actually did write that code and click "compile". What would there be in the 'i' variable? Era Scarecrow already answered the question for you. The correct answer is that the code wouldn't compile. But I just want to see that you understand why it must be so.What do you suppose would happen if I wrote the following? struct A { int _a = 1; B b; struct B { int _b = 1; C c; struct C { int _c = 1; int myMemberFunction() { return _a + _b + _c; } } static int otherFunction() { C cc; return cc.myMemberFunction(); } } } void main() { int i = A.B.otherFunction(); }I was simply using A.B.C.myMemberFunction as a shorthand for whatever name the compiler uses underneath the hood to represent the non-static version of the function.
Feb 02 2013
On Saturday, 2 February 2013 at 17:33:38 UTC, TommiT wrote:I'm sure I'll get by, with a little help from my friends.I was simply using A.B.C.myMemberFunction as a shorthand for whatever name the compiler uses underneath the hood to represent the non-static version of the function.Yes, I can see that now. I didn't understand that the code wasn't actual code but something that the compiler sees. But, you didn't answer my question. What would happen if I actually did write that code and click "compile". What would there be in the 'i' variable? Era Scarecrow already answered the question for you. The correct answer is that the code wouldn't compile. But I just want to see that you understand why it must be so.
Feb 02 2013
On Saturday, 2 February 2013 at 03:50:49 UTC, Zach the Mystic wrote:[..]What do you suppose would happen if I wrote the following? struct A { struct B {} B b1; B b2; } void main() { A a; assert(&a.b1 == &a.b2); }
Feb 01 2013
On Saturday, 2 February 2013 at 06:19:29 UTC, TommiT wrote:On Saturday, 2 February 2013 at 03:50:49 UTC, Zach the Mystic wrote:With my new rules? It would be illegal to take the address of a struct which contained no data. I don't think this will break much code, but I don't know.[..]What do you suppose would happen if I wrote the following? struct A { struct B {} B b1; B b2; } void main() { A a; assert(&a.b1 == &a.b2); }
Feb 02 2013
On Saturday, 2 February 2013 at 17:56:41 UTC, Zach the Mystic wrote:On Saturday, 2 February 2013 at 06:19:29 UTC, TommiT wrote:Yes, that is kind of what I was getting at with my question. But I'm going to ask the same thing in a better way now: Given your new nested struct variable behaviour and my definition of struct 'A' quoted above, would the following lines compile? static assert( A.B.sizeof == 0 ); static assert( A.sizeof == 0 );On Saturday, 2 February 2013 at 03:50:49 UTC, Zach the Mystic wrote:With my new rules? It would be illegal to take the address of a struct which contained no data.[..]What do you suppose would happen if I wrote the following? struct A { struct B {} B b1; B b2; } void main() { A a; assert(&a.b1 == &a.b2); }
Feb 02 2013
On Saturday, 2 February 2013 at 18:47:37 UTC, TommiT wrote:On Saturday, 2 February 2013 at 17:56:41 UTC, Zach the Mystic wrote:Yes, I believe so. I don't see why not.On Saturday, 2 February 2013 at 06:19:29 UTC, TommiT wrote:Yes, that is kind of what I was getting at with my question. But I'm going to ask the same thing in a better way now: Given your new nested struct variable behaviour and my definition of struct 'A' quoted above, would the following lines compile? static assert( A.B.sizeof == 0 ); static assert( A.sizeof == 0 );On Saturday, 2 February 2013 at 03:50:49 UTC, Zach the Mystic wrote:With my new rules? It would be illegal to take the address of a struct which contained no data.[..]What do you suppose would happen if I wrote the following? struct A { struct B {} B b1; B b2; } void main() { A a; assert(&a.b1 == &a.b2); }
Feb 02 2013
On Saturday, 2 February 2013 at 03:50:49 UTC, Zach the Mystic wrote:[..]What I'm trying to tell you through those questions is that what you insists on calling a struct in your proposal is really just a template for a namespace that lives inside a struct or a class. And variables of those nested struct types are the actual namespaces.
Feb 01 2013
On Saturday, 2 February 2013 at 03:50:49 UTC, Zach the Mystic wrote:[..]Then, if we used your proposed nested structs to implement properties, pretty weird things like this would become possible: struct A { int _value; struct B { int get() { return _value; } alias this = get; void opAssign(int v) { _value = v; } } B length; } void func(T)(ref A a, T oldLength) { a.length = 100; // Trying to restore 'a' back to the old length: a.length = oldLength; } void main() { A a; a.length = 5; func(a, a.length); assert(a.length == 100); }
Feb 01 2013
On Saturday, 2 February 2013 at 07:10:00 UTC, TommiT wrote:On Saturday, 2 February 2013 at 03:50:49 UTC, Zach the Mystic wrote:This code is both wrong and has nothing whatever to do with the current topic. Boiling down the template to its resulting function, and imagining _value as the intended entity: void func(ref A a, int oldLength) { a._value = 100; a._value = oldLength; } A a; a._value = 5; func(a, a._value); assert(a._value == 5); // 5, not 100 func takes an int. It's not a reference, it's a copy. Let's assume you meant void func(ref A a, ref int oldLength) {} instead. Well, if you pass a reference, set it, and then refer it, you're going to get the set value back. I'm sorry, you can't adjust a reference and then expect to get a phantom original copy back. While I may have made a mistake, I simply see no connection between this and the idea of properties as structs.[..]Then, if we used your proposed nested structs to implement properties, pretty weird things like this would become possible: struct A { int _value; struct B { int get() { return _value; } alias this = get; void opAssign(int v) { _value = v; } } B length; } void func(T)(ref A a, T oldLength) { a.length = 100; // Trying to restore 'a' back to the old length: a.length = oldLength; } void main() { A a; a.length = 5; func(a, a.length); assert(a.length == 100); }
Feb 02 2013
On Saturday, 2 February 2013 at 17:49:44 UTC, Zach the Mystic wrote:On Saturday, 2 February 2013 at 07:10:00 UTC, TommiT wrote:No, you're not getting it. The following is a function template: void func(T)(ref A a, T oldLength) {...} The type of parameter oldLength is going to be the type of the expression you pass as the second argument when you call func. If you call func like I did in my example: A a; func(a, a.length); ...the type of the second argument to func, a.length, is A.B, and therefore the specialization of func that ends up being called is: void func(ref A a, A.B oldLength) {...} ...and variable a.length is being passed by value, not by reference.On Saturday, 2 February 2013 at 03:50:49 UTC, Zach the Mystic wrote:This code is both wrong and has nothing whatever to do with the current topic. Boiling down the template to its resulting function, and imagining _value as the intended entity: void func(ref A a, int oldLength) { a._value = 100; a._value = oldLength; } A a; a._value = 5; func(a, a._value); assert(a._value == 5); // 5, not 100 func takes an int. It's not a reference, it's a copy. Let's assume you meant void func(ref A a, ref int oldLength) {} instead. Well, if you pass a reference, set it, and then refer it, you're going to get the set value back. I'm sorry, you can't adjust a reference and then expect to get a phantom original copy back. While I may have made a mistake, I simply see no connection between this and the idea of properties as structs.[..]Then, if we used your proposed nested structs to implement properties, pretty weird things like this would become possible: struct A { int _value; struct B { int get() { return _value; } alias this = get; void opAssign(int v) { _value = v; } } B length; } void func(T)(ref A a, T oldLength) { a.length = 100; // Trying to restore 'a' back to the old length: a.length = oldLength; } void main() { A a; a.length = 5; func(a, a.length); assert(a.length == 100); }
Feb 02 2013
On Thursday, 31 January 2013 at 19:13:03 UTC, Zach the Mystic wrote:I'm hoping that the community won't close the books on this issue without even *examining* my proposal, found here: http://forum.dlang.org/thread/kdukid$stg$1 digitalmars.com?page=2#post-yqvrjszzlcpmmuyqyxdz:40forum.dlang.orgI'm just going to repeat the arguments I've already made on the "Property discussion wrap-up" thread against the idea of using a variable as a property: struct MyArray { int _len; // struct2.0 variables have an implicit reference 'outer' to // the enclosing object (don't ask how... not my idea) struct2.0 Len { int opCall() const { return outer._len; } alias this = opCall; void opAssign(int v) const { outer._len = v; } } Len length; // please ignore the memory overhead over here } void func(N)(N n) if (isConvertible!(N,int)) { n = 123; } void main() { MyArray arr; func(arr.length); // changes arr._len (not good) }
Jan 31 2013
On 2013-01-31 19:13:02 +0000, "Zach the Mystic" <reachBUTMINUSTHISzach gOOGLYmail.com> said:Or just shut me up by saying something about why it's just wrong or simply can't work.Don't take it personally. I'm not saying anything about your proposal, or any other proposal for that matter. All I'm saying is that I find it very unlikely that this discussion changes anything. Sorry for being pessimistic. I'm not the one you need to convince, Walter decides in the end. And he has shown little inclination to make changes to how properties works other than some subtle refinements. This was true in 2009, it seems to be even more the case today. -- Michel Fortin michel.fortin michelf.ca http://michelf.ca/
Jan 31 2013
On Thursday, 31 January 2013 at 19:13:03 UTC, Zach the Mystic wrote:I'm hoping that the community won't close the books on this issue without even *examining* my proposal, found here: http://forum.dlang.org/thread/kdukid$stg$1 digitalmars.com?page=2#post-yqvrjszzlcpmmuyqyxdz:40forum.dlang.orgI don't think the community is ready to close the books on this. and Properties. And that was purely at the syntactic level. And have a similar issue with Java's introduction of foreach. Why does it have to be so hard to remember the syntax of these very simple constructs! Anyway, I don't see what your plan offers from just fixing property to do what is needed. I've also got overwhelmed by the complexity to writing properties.
Jan 31 2013
On Thursday, 31 January 2013 at 15:40:19 UTC, Michel Fortin wrote:On 2013-01-31 14:50:40 +0000, "Steven Schveighoffer" <schveiguy yahoo.com> said:Also if you're worried about the code breakage necessary to get properties as structs, i.e. nested structs must now have "static" in front of them, consider: 1) That having structs which are nested inside functions hold a pointer without having structs nested in structs do the same thing is an inconsistent language feature. 2) Second, that such struct will still work in all cases where an outer name is not being shadowed. They will simply suffer performance costs of having a needless pointer attached. Also, is it really asking people too much to tag nested structs with "static" now?It actually is a bit depressing, we have to reset the clock back to late 2009 to start over with properties...I haven't participated in the discussions about properties this time around because it's pretty obvious to me it's getting nowhere. It seems to me that nothing can be done at this point in time if we want to avoid a breakage of almost all current D code.
Jan 31 2013
Static nested struct as property... what is going on... In this case is better to simply rid-off property keyword. "Properties" are better implemented where they created. Maybe have bugs in design, but I think that property should be a simple access method/function without struct-and-whatever-else kung-fu code.
Jan 31 2013
On Thursday, 31 January 2013 at 01:26:19 UTC, Steven Schveighoffer wrote:On Tue, 29 Jan 2013 23:57:14 -0500, Jesse Phillips <Jessekphillips+d gmail.com> wrote:Thank you.Sorry I have to oppose this. It is in no way a compromise as it is completely different from everything suggested. I'm going to take this opportunity to highjack your thread.You are welcome to it! I don't know if there is a thread on this newsgroup about properties that hasn't been hijacked.I should explain that my reasoning behind this is: 1. Walter wants to get rid of propertyI can't really speak to what Walter wants, but I think there is more to it than removing a keyword.2. Dispite 4 years of assuming property will be implemented, the old D1-style crap is still in place.Yep, I thought its introduction meant things were going to break, and also that other things would work.The compromise is: OK, you want to ditch property? I can live with that as long as we have some way to designate properties. How about this?I don't think that is a compromise as i don't believe it is property that is slated for removal, it is designating something a property.Yep, totally thought that was coming. I'd still be ok with it, but I'm still partial to not having it enforced, would rather see field -> property a seamless transition.Can an pro- property members claim that the current behavior is what you want? I believe this answer is no.The answer is no, but only because what we asked for was never implemented. What was ORIGINALLY designed with property (enforcement of parentheses on functions, enforcement against parentheses on properties) is what we wanted.Yes, but I was thinking more on the degree of wrongness that is currently acceptable. Something to think on for what my proposal would be. But again, I don't care about the appearance, only behavior.It seems at least some members for property feel that currently functions are being annotated with property that shouldn't be.This is unavoidable. It's like saying I feel some functions are incorrectly named. property has nothing to do with it. There is no "right" answer to whether something should be a property or not, just like there is no "right" name for a function.Walter's suggestion isn't (D1) implementation it address some concerns with the existing behavior, but doesn't give you a way to declare properties. I think his suggestions need implemented regardless of what we do with property. I think Walter just felt this would appease the pro-property.It also seems those for property aren't fighting optional parens as much? Can we discuss fixing the issues we have with this. I think a good change is to require parens if returning a callable (opposite of Walters suggestion).Yes, if the choice is between having the previous implementation (D1) and optional parentheses with a way to designate properties, I'll choose the latter.What purpose is that? Isn't it a no-op by default, and barely enforce () with -property?If I have my above claims mostly correct, then I'd say property needs to be put back in the drawing board and re-implemented.If you want to replace property, we need a replacement. property still serves a purpose, even in it's currently crippled form.I'm not sure if we are going to have a complete replacement, but your right, we can leave it in until such a choice is finalized, but let us get rid of -property.I'd be for removing it from the language and if we decide on what in needs to enforce and should be part of the language, then its implementation is completed in a feature branch and remains out of the language until it meets the needed enforcement and behavior.Fine, but leave property in until you have completed the replacement feature.Ah, your subtle bias shines through ;):)The real fact of the matter is, if D never had the "hack" properties it did, I actually wouldn't care. Calling functions instead of setting or getting properties is not that horrible. But writeln = "hi" is horrible.Yep, introducing properties would have been easy, because no one would have fallen for the joys of optional parens. writeln = "hi" would not compile with Walters suggested changes.In general, the idea is to implement fields without having to create storage for them. It will never perform as well as a field.I know, but you can't trust when reading code that is what happens. And having that convention was being argued for, I like Walter's position of having the compiler make guarantees and not conventions (I'm sure I've got some exception I'd want but can't think of one).In other words, go back to D1 properties. No thanks.Again, it wouldn't be D1, and we aren't going back because that is what we currently have. We need to fix it.-SteveThanks for the feedback.
Jan 31 2013
On 1/31/13 7:01 PM, Jesse Phillips wrote:I don't think that is a compromise as i don't believe it is property that is slated for removal, it is designating something a property.FWIW we want to keep a means to define properties. Andrei
Jan 31 2013
On Friday, February 01, 2013 01:01:02 Jesse Phillips wrote:I think his suggestions need implemented regardless of what we do with property. I think Walter just felt this would appease the pro-property.Well, it doesn't even come close. For the most part, the pro- property folks want explicit proprties, and that's precisely what Walter is proposing that we get rid of.writeln = "hi" would not compile with Walters suggested changes.Only because it's variadic. Something like range.popFrontN = 7; _would_ compile. And that's just as bad. We need explicit setter properties in order to avoid letting assignment work with functions where it makes no sense for it to work. - Jonathan M Davis
Jan 31 2013
On 1/31/13 10:14 PM, Jonathan M Davis wrote:On Friday, February 01, 2013 01:01:02 Jesse Phillips wrote:Under some proposals range.popFrontN = 7 would not compile because there's no corresponding range.popFrontN that yields an int. AndreiI think his suggestions need implemented regardless of what we do with property. I think Walter just felt this would appease the pro-property.Well, it doesn't even come close. For the most part, the pro- property folks want explicit proprties, and that's precisely what Walter is proposing that we get rid of.writeln = "hi" would not compile with Walters suggested changes.Only because it's variadic. Something like range.popFrontN = 7; _would_ compile. And that's just as bad. We need explicit setter properties in order to avoid letting assignment work with functions where it makes no sense for it to work.
Jan 31 2013
On Thu, 31 Jan 2013 22:38:04 -0500, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:On 1/31/13 10:14 PM, Jonathan M Davis wrote:I don't think this rule is good enough. You are inviting strange properties to invade your types, especially with the advent of UFCS. -SteveOn Friday, February 01, 2013 01:01:02 Jesse Phillips wrote:Under some proposals range.popFrontN = 7 would not compile because there's no corresponding range.popFrontN that yields an int.I think his suggestions need implemented regardless of what we do with property. I think Walter just felt this would appease the pro-property.Well, it doesn't even come close. For the most part, the pro- property folks want explicit proprties, and that's precisely what Walter is proposing that we get rid of.writeln = "hi" would not compile with Walters suggested changes.Only because it's variadic. Something like range.popFrontN = 7; _would_ compile. And that's just as bad. We need explicit setter properties in order to avoid letting assignment work with functions where it makes no sense for it to work.
Jan 31 2013
On 1/31/13 11:41 PM, Steven Schveighoffer wrote:On Thu, 31 Jan 2013 22:38:04 -0500, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:I agree. Was just sayin'. AndreiOn 1/31/13 10:14 PM, Jonathan M Davis wrote:I don't think this rule is good enough. You are inviting strange properties to invade your types, especially with the advent of UFCS.On Friday, February 01, 2013 01:01:02 Jesse Phillips wrote:Under some proposals range.popFrontN = 7 would not compile because there's no corresponding range.popFrontN that yields an int.I think his suggestions need implemented regardless of what we do with property. I think Walter just felt this would appease the pro-property.Well, it doesn't even come close. For the most part, the pro- property folks want explicit proprties, and that's precisely what Walter is proposing that we get rid of.writeln = "hi" would not compile with Walters suggested changes.Only because it's variadic. Something like range.popFrontN = 7; _would_ compile. And that's just as bad. We need explicit setter properties in order to avoid letting assignment work with functions where it makes no sense for it to work.
Jan 31 2013
On Thu, 31 Jan 2013 19:01:02 -0500, Jesse Phillips <Jessekphillips+D gmail.com> wrote:On Thursday, 31 January 2013 at 01:26:19 UTC, Steven Schveighoffer wrote:I meant the property design, including the keyword. Basically whatever property was supposed to stand for.On Tue, 29 Jan 2013 23:57:14 -0500, Jesse Phillips <Jessekphillips+d gmail.com> wrote:Thank you.Sorry I have to oppose this. It is in no way a compromise as it is completely different from everything suggested. I'm going to take this opportunity to highjack your thread.You are welcome to it! I don't know if there is a thread on this newsgroup about properties that hasn't been hijacked.I should explain that my reasoning behind this is: 1. Walter wants to get rid of propertyI can't really speak to what Walter wants, but I think there is more to it than removing a keyword.I don't think that's the case. D1 has a designation of what is a property -- if it has no arguments it is a getter, if it has a single argument it is a setter. The extra rules Walter is proposing are a half-baked design that covers some cases. But the rules are controlling the behavior based on superficial observations instead of allowing an author to express specific intents. It sounds like something Congress would come up with...The compromise is: OK, you want to ditch property? I can live with that as long as we have some way to designate properties. How about this?I don't think that is a compromise as i don't believe it is property that is slated for removal, it is designating something a property.First, it's not seamless without a keyword or special syntax (remember the delegate problem). Second, that's not a mutually exclusive choice. If you enforce property syntax, then it's still seamless (and even more so since you actually *CAN* implement what is desired).Yep, totally thought that was coming. I'd still be ok with it, but I'm still partial to not having it enforced, would rather see field -> property a seamless transition.Can an pro- property members claim that the current behavior is what you want? I believe this answer is no.The answer is no, but only because what we asked for was never implemented. What was ORIGINALLY designed with property (enforcement of parentheses on functions, enforcement against parentheses on properties) is what we wanted.Then why ever have properties at all? Functions work just fine.Yes, but I was thinking more on the degree of wrongness that is currently acceptable. Something to think on for what my proposal would be. But again, I don't care about the appearance, only behavior.It seems at least some members for property feel that currently functions are being annotated with property that shouldn't be.This is unavoidable. It's like saying I feel some functions are incorrectly named. property has nothing to do with it. There is no "right" answer to whether something should be a property or not, just like there is no "right" name for a function.I think you are misunderstanding his proposal. Under his proposal, two completely unrelated and unconnected functions could combine together to allow a setter that is completely unintended. Instead of specifying intent, we have to jump through the compiler hoops to avoid accidental intent. This is not a solution, it's actually worse than D1 style properties. You'll have code that can call a 'setter' on an object or struct with no 'getter' and you'll have no idea why.Walter's suggestion isn't (D1) implementation it address some concerns with the existing behavior, but doesn't give you a way to declare properties.It also seems those for property aren't fighting optional parens as much? Can we discuss fixing the issues we have with this. I think a good change is to require parens if returning a callable (opposite of Walters suggestion).Yes, if the choice is between having the previous implementation (D1) and optional parentheses with a way to designate properties, I'll choose the latter.I think his suggestions need implemented regardless of what we do with property. I think Walter just felt this would appease the pro-property.I certainly hope none of his suggestions are implemented, they will only confuse the situation.The purpose is to specify intent "I declare this is a property, use it that way". It's the whole point of having a property syntax. It's just not enforced by the compiler. The compiler has numerous bugs on it, that doesn't mean the features should be ditched, it means we have to correctly implement those features. array.dup allows implicit casting away from immutable (at least it did, not sure if that was fixed). Does that mean we should get rid of dup?What purpose is that? Isn't it a no-op by default, and barely enforce () with -property?If I have my above claims mostly correct, then I'd say property needs to be put back in the drawing board and re-implemented.If you want to replace property, we need a replacement. property still serves a purpose, even in it's currently crippled form.That doesn't hurt anything, that switch is an experimental feature, and once we have the blessed property syntax, we likely will need that experimental feature to obey the new syntax.I'm not sure if we are going to have a complete replacement, but your right, we can leave it in until such a choice is finalized, but let us get rid of -property.I'd be for removing it from the language and if we decide on what in needs to enforce and should be part of the language, then its implementation is completed in a feature branch and remains out of the language until it meets the needed enforcement and behavior.Fine, but leave property in until you have completed the replacement feature.I see only minor issue with optional parens. It's the setters that are the most disruptive.The real fact of the matter is, if D never had the "hack" properties it did, I actually wouldn't care. Calling functions instead of setting or getting properties is not that horrible. But writeln = "hi" is horrible.Yep, introducing properties would have been easy, because no one would have fallen for the joys of optional parens.writeln = "hi" would not compile with Walters suggested changes.No, but other abuses would.The compiler cannot make performance guarantees of any kind really. That is up to convention. Properties do provide a *mechanism* to create a convention. What the convention is remains the will of the author.In general, the idea is to implement fields without having to create storage for them. It will never perform as well as a field.I know, but you can't trust when reading code that is what happens. And having that convention was being argued for, I like Walter's position of having the compiler make guarantees and not conventions (I'm sure I've got some exception I'd want but can't think of one).OK, I stand corrected, if it is a choice between D1 properties and Walter's new rules, I'll choose D1 properties. At least I know what I get there. But if we have *any* property syntax at all, I'd prefer that. Even the current design, while not implemented, has the PROMISE of having a fully functional property syntax. I prefer the promise of something that is usable to something that is utterly useless, even if it's already implemented. -SteveIn other words, go back to D1 properties. No thanks.Again, it wouldn't be D1, and we aren't going back because that is what we currently have. We need to fix it.
Jan 31 2013
As proposal: class Example { public int IntProperty { get; private set; } private double _internalMember; double FloatProperty { get out { assert(result > 0); } body { return _internalMember * 42; } set in { assert(value != 0); } body { _internalMember = value + 42; } } } Resulting code: class Example { private _autoGeneratedBackMember; public int get_IntProperty() { return _autoGeneratedBackMember; } private void set_IntProperty(int value) { _autoGeneratedBackMember = value; } public { double get_FloatProperty() out(result) { assert(result > 0); } body { return _internalMember * 42; } void set_FloatPoperrty(double value) in { assert(value0); } body { _internalMember = value + 42; }} } 1. Rid-of property keyword, UFCS as they now. Optional parentheses for UFCS with one or two parameters, not for variable number of arguments. address of property, ref property, property rewrite, virtual property, explicit get/set methods, property with value semantic, exlicit calling get/set methods etc. 3. Property can be exported to libray as "<out type> get_<Name>(), void set_<Name>(<in type>)". 4. Get property always have only out(result) { } contract. 5. Set property always have only in { } contract. Thanks.
Feb 02 2013