digitalmars.D - Fixing const arrays
- Andrei Alexandrescu (42/42) Dec 10 2011 Walter and I discussed today and decided to fix this long-standing issue...
- Adam D. Ruppe (2/4) Dec 10 2011 Thank you. Finally.
- Jonathan M Davis (31/32) Dec 10 2011 [snip]
- deadalnix (3/45) Dec 10 2011 I love to see that. This is going the right way.
- kenji hara (19/59) Dec 10 2011 Treating whole constant arrays as ranges by automatically shedding the
- deadalnix (4/73) Dec 10 2011 This is just about removing the constness for whatever the part of a
- Andrei Alexandrescu (11/19) Dec 10 2011 The problem here is scale. We're looking at an absolutely massive code
- Andrei Alexandrescu (5/13) Dec 10 2011 I should add there is precedent. C++ also removes top-level const when
- kenji hara (22/37) Dec 10 2011 Hmm, it's for sure.
- Timon Gehr (7/21) Dec 10 2011 Yes, but in C++ const is not transitive, so this change necessarily
- kenji hara (13/54) Dec 10 2011 OK. I agree to the suggestion.
- kenji hara (7/61) Dec 10 2011 Posted a test patch to realize the suggestion.
- Andrei Alexandrescu (3/6) Dec 10 2011 Many thanks, Kenji, for executing so fast on this!
- bearophile (10/12) Dec 10 2011 I think that change proposed by Andrei A. (that I like) doesn't add a sp...
- kenji hara (10/22) Dec 10 2011 I mean following code comment will not become true.
- Jonathan M Davis (15/28) Dec 10 2011 Why does that matter? What does it affect?
- Jonathan M Davis (19/28) Dec 10 2011 Making the fix in Phobos is a pain in that you have to duplicate functio...
- Michel Fortin (16/18) Dec 10 2011 It seems strange that if you implemented the exact same semantic as an
- Andrei Alexandrescu (23/36) Dec 10 2011 I do worry about those things, and this decision comes at the end of a
- Jonathan M Davis (13/50) Dec 10 2011 I think that it's completely justified. We need a way to define tail-con...
- Andrei Alexandrescu (4/16) Dec 11 2011 I'm not sure. How many times have you been in a place in life where you
- Mehrdad (3/6) Dec 11 2011 Hmmm.. isn't that precisely what happens when you define a 'const'
- Andrei Alexandrescu (4/11) Dec 11 2011 What do you do inside that method? It's reasonable to not expect to
- Mehrdad (6/9) Dec 11 2011 Not sure right now, but something along the lines of
- Andrei Alexandrescu (4/14) Dec 11 2011 I think you should write:
- Mehrdad (3/6) Dec 11 2011 Ah good point, I forgot about that. Idk then.
- Walter Bright (3/12) Dec 11 2011 Try the new beta
- Mehrdad (4/6) Dec 11 2011 WHOA nice, the reduce() example worked!! :D Thanks for taking the time
- David Nadlinger (7/13) Dec 11 2011 No, it's correct like that, save() is a @property.
- Mehrdad (23/38) Dec 11 2011 Whoa what?! I didn't know save() is a @property. In that case I stand
- Tobias Pankrath (1/18) Dec 11 2011 I agree.
- Jonathan M Davis (8/27) Dec 11 2011 It was debated some time ago, and it ended up being a property. The fact...
- Max Samukha (9/36) Dec 12 2011 Reminds me of .NET's Object.GetHashCode() method, which should be a
- torhu (19/25) Dec 12 2011 I really don't get this. When D has 10,000 programmers using it
- Jakob Ovrum (6/38) Dec 12 2011 Furthermore, there weren't even a way to enforce the property
- Michel Fortin (9/14) Dec 12 2011 Indeed. As far as we know, there might be more people out there using
- Adam D. Ruppe (3/5) Dec 12 2011 The real WTF is that someone decided @property should be used for
- Manu (10/39) Dec 12 2011 I completely agree. One thing that most excited me about D at this stage...
- Andrei Alexandrescu (6/8) Dec 12 2011 Changing from r.save to r.save() is NOT an important change. It makes no...
- Jakob Ovrum (20/30) Dec 12 2011 The whole point of a property to begin with is to make it look
- Andrei Alexandrescu (3/7) Dec 12 2011 Why? Save does behave like a field for the vast majority of structs.
- Jakob Ovrum (4/14) Dec 12 2011 But save is an abstract interface function, its signature should
- Timon Gehr (3/15) Dec 12 2011 Under the premise that a function should be a property iff it behaves
- Jakob Ovrum (6/22) Dec 12 2011 Adding on this: I have no problem with save being a property if
- Andrei Alexandrescu (3/15) Dec 12 2011 Same goes for many properties.
- Jakob Ovrum (22/43) Dec 12 2011 This is true, and many functions marked @property arguably
- Jonathan M Davis (5/11) Dec 12 2011 Both save and postblit are supposed to be trivial. Algorithms generally ...
- Adam D. Ruppe (4/6) Dec 12 2011 If we start removing features because someone can use them
- Jakob Ovrum (8/14) Dec 12 2011 Firstly, no feature is removed, it is changed, unless you
- Andrei Alexandrescu (3/6) Dec 12 2011 We could have defined a system much better than both.
- Jakob Ovrum (8/15) Dec 12 2011 I definitely agree. I think the current situation sucks.
- Vladimir Panteleev (6/10) Dec 13 2011 I don't think that's a problem.
- Jonathan M Davis (4/6) Dec 12 2011 Aside from the fact that the behavior of -property isn't the default, wh...
- Andrei Alexandrescu (4/9) Dec 12 2011 Other than it being completely useless, requiring more rote
- Steven Schveighoffer (4/14) Dec 12 2011 Wait, are we talking about @property or .save?
- Timon Gehr (2/17) Dec 13 2011 definitely @property.
- Jonathan M Davis (19/29) Dec 13 2011 So, you prefer the situation where any function with no arguments can be...
- Andrei Alexandrescu (3/16) Dec 13 2011 No. That would be a false choice.
- Jonathan M Davis (5/24) Dec 13 2011 I'm not saying that those are the only choices, but you seem to think th...
- Andrei Alexandrescu (4/27) Dec 13 2011 There's a phrase in Romanian that quite applies: "From the lake into the...
- Vladimir Panteleev (7/9) Dec 13 2011 I believe the English version is "Out of the frying pan, into the
- Peter Alexander (17/24) Dec 13 2011 In my opinion, it's not better than nothing.
- Andrei Alexandrescu (10/37) Dec 13 2011 We could have inferred property intention from the code pattern, without...
- Michel Fortin (40/44) Dec 13 2011 By "code patterns", you mean something like this?
- Jonathan M Davis (23/70) Dec 13 2011 'd
- Regan Heath (24/42) Dec 14 2011 =
- Regan Heath (9/51) Dec 14 2011 d =
- Michel Fortin (23/42) Dec 14 2011 I know the basics of the C# property syntax, but how do you take the
- Regan Heath (31/54) Dec 14 2011 I hadn't given this a lot of thought. But, here goes.. :)
- Steven Schveighoffer (23/70) Dec 14 2011 @property wasn't my first choice, there were probably a dozen proposals ...
- Andrej Mitrovic (6/6) Dec 14 2011 I don't mind @property, usually I just create one property block for a
- Timon Gehr (3/30) Dec 13 2011 ??? T[].length is a field access, not a property function. It takes a
- Peter Alexander (6/33) Dec 13 2011 Assigning to the length of an array may reallocate it, which is not a
- Timon Gehr (3/38) Dec 14 2011 OK, I see, thanks. I don't think it is problematic in this particular
- Peter Alexander (22/62) Dec 14 2011 Well, it is a little. It makes it difficult to scan code looking for GC
- Timon Gehr (7/71) Dec 14 2011 Oh yes, certainly. That is what I meant by 'in this particular case':
- bearophile (4/10) Dec 14 2011 A proposed idea to help is to add a compilation switch that produces a l...
- Steven Schveighoffer (14/79) Dec 14 2011 Yes, but length as a read property does not allocate anything (nor does ...
- bearophile (4/7) Dec 14 2011 sort and reverse properties will be deprecated and later removed.
- Peter Alexander (9/98) Dec 14 2011 It's not that I wouldn't expect it (I would), but at a glance (i.e.
- simendsjo (3/7) Dec 14 2011 The Norwegian version is "From ashes to fire" (direct translation) or
- Jonathan M Davis (3/29) Dec 13 2011 In fact, what _would_ you prefer to @property if it's not what we had be...
- Andrei Alexandrescu (3/4) Dec 12 2011 I'm not so sure.
- torhu (10/14) Dec 12 2011 Why? As far as I can tell, it's inconsistent with what properties are
- Andrei Alexandrescu (8/26) Dec 12 2011 So if we called .save .state or .current things would be any different?
- torhu (9/35) Dec 12 2011 Yes, completely. The whole property concept is basically a naming
- Peter Alexander (8/20) Dec 12 2011 My understanding is the properties are essentially meant to be
- Jonathan M Davis (21/54) Dec 12 2011 A property is essentially an abstraction to treat a function like a memb...
- torhu (15/62) Dec 12 2011 It's actually not 'save' being a noun that's the problem. I just
- Jonathan M Davis (7/24) Dec 12 2011 You can pretty much always come up with another function with a complete...
- torhu (2/19) Dec 12 2011 Yes, that's my opinion too.
- Steven Schveighoffer (7/48) Dec 12 2011 The very definition of save is that it's only defined if it's fast. So ...
- bearophile (4/6) Dec 11 2011 How many times I have used reduce or map on constant arrays in D2? Only ...
- Andrei Alexandrescu (3/13) Dec 11 2011 Andrei
- Jonathan M Davis (30/53) Dec 13 2011 I tend to avoid const ranges precisely because they pretty much never wo...
- bearophile (4/6) Dec 14 2011 This is what I was trying to answer to Andrei :-)
- Michel Fortin (16/23) Dec 11 2011 Sadly, I'm not using D in my daily work these days. It's mostly C++ and
- Jacob Carlborg (5/23) Dec 12 2011 It seems 64bit support will be available in the upcoming release (DMD
- dsimcha (6/8) Dec 11 2011 Really silly question: Why not do the same for primitives (int, float,
- Andrei Alexandrescu (3/11) Dec 11 2011 Yes, that would be good to do as well.
- deadalnix (2/14) Dec 11 2011 I was thinking about sugesting this. So obviously, this is a +1 to me.
- Timon Gehr (3/15) Dec 11 2011 +1. This also reduces template bloat, because IFTI wont create different...
- Jonathan M Davis (25/37) Dec 11 2011 Actually, that could be a problem for some stuff. It might be an accepta...
- Timon Gehr (4/28) Dec 11 2011 Those issues are inexistent. int and immutable(int) are implicitly
- Jonathan M Davis (10/46) Dec 11 2011 They may be implicitly convertible, but if you just outright stripped co...
- Timon Gehr (4/50) Dec 11 2011 The qualifiers are stripped from the actual arguments, not from the
- Andrei Alexandrescu (4/36) Dec 11 2011 Timon is right, there's no issue. Top-level qualifier would be stripped
- deadalnix (9/46) Dec 11 2011 I think you misunderstood the idea. The point was to remove constness of...
- Max Samukha (19/23) Dec 12 2011 Then, should the rule be generalized to include any type that has no
- Steven Schveighoffer (12/57) Dec 12 2011 T does not lose its constness here. const(U[]) would go to const(U)[], ...
Walter and I discussed today and decided to fix this long-standing issue: import std.algorithm; void main() { const arr = [1, 2, 3]; reduce!"a*b"(arr); } The problem here is that D's built-in arrays are at the same time containers and their own ranges. When the array is constant the matter becomes confusing because the range itself must be non-constant such that it can iterate the constant array. Put simply, the type of the array in this case should be const(int[]) and the type of its range should be const(int)[]. This problem does not commonly occur with ranges because people do expect that a constant range can't be used for iteration, and an elaborate container will emit the proper type of range even when the container itself is constant. We decided to fix this issue by automatically shedding the top-level const when passing an array or a pointer by value into a function. The rule is simple and does not complicate lookup rules, type deduction, or template specialization. It is a semantic rewrite as follows. Consider x an array of type qualifier(T[]). In any function call in which it is established that x is passed by value (i.e. no "ref" with the parameter), the call: fun(..., x, ...) is lowered into: fun(..., cast(qualifier(T)[]) x, ...) after which the usual language rules apply. Similarly, if x has type qualifier(T*), AND if x is passed by value into a function, the call: fun(..., x, ...) is lowered into: fun(..., cast(qualifier(T)*) x, ...) after which, again, the usual rules apply. Note that fun does not need to be a template and generally must meet no special conditions aside from taking x by value. If fun takes specifically a const(T[]), the call will go through no problem because const(T)[] is implicitly convertible to const(T[]). This allows template functions to accept arrays by value yet modify their own private copy of the array's bounds, which is reasonable and expected. This rule solves a host of issues related to applying range algorithms to arrays. I hope we will have this rule in action in dmd 2.057. Andrei
Dec 10 2011
Andrei Alexandrescu Wrote:We decided to fix this issue by automatically shedding the top-level const when passing an array or a pointer by value into a function.Thank you. Finally.
Dec 10 2011
On Saturday, December 10, 2011 15:47:13 Andrei Alexandrescu wrote:Walter and I discussed today and decided to fix this long-standing issue:[snip] This looks like a solid decision, and I was actually about to suggest it when thinking about the issues with const ranges today. It's the only sensible solution that I can think of. I was wondering if there might be any negative side effects to it, but I haven't been able to think of any. It would be nice to do the same thing with static arrays, but that would make it harder to pass static arrays to templated functions, and it actually becomes quite dangerous, since it then becomes very easy to mistakenly return references to that static array when the scope is exited. So, I think that the issue of having to slice static arrays should probably remain, but unlike dynamic arrays, static arrays _do_ own their memory, so it's quite reasonably to have to slice them IMHO. The other remaining issue is how to handle tail-const in the general case. Ideally, there would be a way to return a tail-const range from a const range. The only way I can think of enabling that at the moment is to make it so that if opSlice is defined for a type, and it returns the same type (save for how const or immutable it is), then it could be treated the same way as arrays would be as far as template instantiations go (that is, the newly suggested way). But I don't know quite what side-effects that has. Still, I do think that we should find a way to define tail-constness for ranges which are user-defined types. It's not as critical as with arrays, but given the transivity of const, it's still important, since it can be very easy to end up in a situation where it becomes somewhat problematic to get a tail-const range when you're using const much. In any case, I applaud this decision. It should definitely help dealing with arrays as ranges easier. The fact that const and immutable don't work very well at all with ranges at this point is problematic given how const and immutable are supposed to be major features of the language, and this is definitely a step in the right direction. - Jonathan M Davis
Dec 10 2011
Le 10/12/2011 22:47, Andrei Alexandrescu a écrit :Walter and I discussed today and decided to fix this long-standing issue: import std.algorithm; void main() { const arr = [1, 2, 3]; reduce!"a*b"(arr); } The problem here is that D's built-in arrays are at the same time containers and their own ranges. When the array is constant the matter becomes confusing because the range itself must be non-constant such that it can iterate the constant array. Put simply, the type of the array in this case should be const(int[]) and the type of its range should be const(int)[]. This problem does not commonly occur with ranges because people do expect that a constant range can't be used for iteration, and an elaborate container will emit the proper type of range even when the container itself is constant. We decided to fix this issue by automatically shedding the top-level const when passing an array or a pointer by value into a function. The rule is simple and does not complicate lookup rules, type deduction, or template specialization. It is a semantic rewrite as follows. Consider x an array of type qualifier(T[]). In any function call in which it is established that x is passed by value (i.e. no "ref" with the parameter), the call: fun(..., x, ...) is lowered into: fun(..., cast(qualifier(T)[]) x, ...) after which the usual language rules apply. Similarly, if x has type qualifier(T*), AND if x is passed by value into a function, the call: fun(..., x, ...) is lowered into: fun(..., cast(qualifier(T)*) x, ...) after which, again, the usual rules apply. Note that fun does not need to be a template and generally must meet no special conditions aside from taking x by value. If fun takes specifically a const(T[]), the call will go through no problem because const(T)[] is implicitly convertible to const(T[]). This allows template functions to accept arrays by value yet modify their own private copy of the array's bounds, which is reasonable and expected. This rule solves a host of issues related to applying range algorithms to arrays. I hope we will have this rule in action in dmd 2.057. AndreiI love to see that. This is going the right way. You deserve your wikipedia page (semi private joke inside).
Dec 10 2011
Treating whole constant arrays as ranges by automatically shedding the top-level const is good. But realizing it by language semantic change is definitely bad.It breaks IFTI rule, and adding special case will make difficult to learn language. Instead of language change, we can add specializations that receive non-ranges and convert them to ranges by removing top-level const. I believe that it is Phobos issue and is never the issue of language. Kenji 2011/12/11 Andrei Alexandrescu <SeeWebsiteForEmail erdani.org>:Walter and I discussed today and decided to fix this long-standing issue: import std.algorithm; void main() { =A0const arr =3D [1, 2, 3]; =A0reduce!"a*b"(arr); } The problem here is that D's built-in arrays are at the same time contain=ersand their own ranges. When the array is constant the matter becomes confusing because the range itself must be non-constant such that it can iterate the constant array. Put simply, the type of the array in this case should be const(int[]) and the type of its range should be const(int)[]. This problem does not commonly occur with ranges because people do expect that a constant range can't be used for iteration, and an elaborate container will emit the proper type of range even when the container itse=lfis constant. We decided to fix this issue by automatically shedding the top-level cons=twhen passing an array or a pointer by value into a function. The rule is simple and does not complicate lookup rules, type deduction, =ortemplate specialization. It is a semantic rewrite as follows. Consider x an array of type qualifier(T[]). In any function call in which=itis established that x is passed by value (i.e. no "ref" with the paramete=r),the call: fun(..., x, ...) is lowered into: fun(..., cast(qualifier(T)[]) x, ...) after which the usual language rules apply. Similarly, if x has type qualifier(T*), AND if x is passed by value into a function, the call: fun(..., x, ...) is lowered into: fun(..., cast(qualifier(T)*) x, ...) after which, again, the usual rules apply. Note that fun does not need to=bea template and generally must meet no special conditions aside from takin=g xby value. If fun takes specifically a const(T[]), the call will go throug=hno problem because const(T)[] is implicitly convertible to const(T[]). This allows template functions to accept arrays by value yet modify their own private copy of the array's bounds, which is reasonable and expected. This rule solves a host of issues related to applying range algorithms to arrays. I hope we will have this rule in action in dmd 2.057. Andrei
Dec 10 2011
This is just about removing the constness for whatever the part of a type that is passed by value. This is not really a special rule and make sense. Le 10/12/2011 23:31, kenji hara a écrit :Treating whole constant arrays as ranges by automatically shedding the top-level const is good. But realizing it by language semantic change is definitely bad.It breaks IFTI rule, and adding special case will make difficult to learn language. Instead of language change, we can add specializations that receive non-ranges and convert them to ranges by removing top-level const. I believe that it is Phobos issue and is never the issue of language. Kenji 2011/12/11 Andrei Alexandrescu<SeeWebsiteForEmail erdani.org>:Walter and I discussed today and decided to fix this long-standing issue: import std.algorithm; void main() { const arr = [1, 2, 3]; reduce!"a*b"(arr); } The problem here is that D's built-in arrays are at the same time containers and their own ranges. When the array is constant the matter becomes confusing because the range itself must be non-constant such that it can iterate the constant array. Put simply, the type of the array in this case should be const(int[]) and the type of its range should be const(int)[]. This problem does not commonly occur with ranges because people do expect that a constant range can't be used for iteration, and an elaborate container will emit the proper type of range even when the container itself is constant. We decided to fix this issue by automatically shedding the top-level const when passing an array or a pointer by value into a function. The rule is simple and does not complicate lookup rules, type deduction, or template specialization. It is a semantic rewrite as follows. Consider x an array of type qualifier(T[]). In any function call in which it is established that x is passed by value (i.e. no "ref" with the parameter), the call: fun(..., x, ...) is lowered into: fun(..., cast(qualifier(T)[]) x, ...) after which the usual language rules apply. Similarly, if x has type qualifier(T*), AND if x is passed by value into a function, the call: fun(..., x, ...) is lowered into: fun(..., cast(qualifier(T)*) x, ...) after which, again, the usual rules apply. Note that fun does not need to be a template and generally must meet no special conditions aside from taking x by value. If fun takes specifically a const(T[]), the call will go through no problem because const(T)[] is implicitly convertible to const(T[]). This allows template functions to accept arrays by value yet modify their own private copy of the array's bounds, which is reasonable and expected. This rule solves a host of issues related to applying range algorithms to arrays. I hope we will have this rule in action in dmd 2.057. Andrei
Dec 10 2011
On 12/10/11 4:31 PM, kenji hara wrote:Treating whole constant arrays as ranges by automatically shedding the top-level const is good. But realizing it by language semantic change is definitely bad.It breaks IFTI rule, and adding special case will make difficult to learn language.There is no breakage of IFTI, just a reduction of what IFTI sees.Instead of language change, we can add specializations that receive non-ranges and convert them to ranges by removing top-level const. I believe that it is Phobos issue and is never the issue of language.The problem here is scale. We're looking at an absolutely massive code duplication for every single function. I don't think this will ever work; if we do it in Phobos it will make Phobos and by extension the language more difficult to understand AND more bloated for the sake of needless consistency. The language change is legitimate when you think of it this way - it gives template functions back the natural right to change their local state. This right was already there for non-template functions. Andrei
Dec 10 2011
On 12/10/11 4:31 PM, kenji hara wrote:Treating whole constant arrays as ranges by automatically shedding the top-level const is good. But realizing it by language semantic change is definitely bad.It breaks IFTI rule, and adding special case will make difficult to learn language. Instead of language change, we can add specializations that receive non-ranges and convert them to ranges by removing top-level const. I believe that it is Phobos issue and is never the issue of language.I should add there is precedent. C++ also removes top-level const when passing objects by value to templates. Deducing top-level const with pass-by-value is inherently nonsensical. Andrei
Dec 10 2011
2011/12/11 Andrei Alexandrescu <SeeWebsiteForEmail erdani.org>:On 12/10/11 4:31 PM, kenji hara wrote:Hmm, it's for sure. ---- void print_type(int){} template <typename T> void f(T p) { int n; p = &n; // OK, head is mutable //*p = 10; // NG, tail is const print_type(p); // Error: need explicit cast from int const * to int // T is deduced as int const * == top const is removed } int main() { int n; int const * const p = &n; f(p); return 0; } KenjiTreating whole constant arrays as ranges by automatically shedding the top-level const is good. But realizing it by language semantic change is definitely bad.It breaks IFTI rule, and adding special case will make difficult to learn language. Instead of language change, we can add specializations that receive non-ranges and convert them to ranges by removing top-level const. I believe that it is Phobos issue and is never the issue of language.I should add there is precedent. C++ also removes top-level const when passing objects by value to templates. Deducing top-level const with pass-by-value is inherently nonsensical. Andrei
Dec 10 2011
On 12/10/2011 11:41 PM, Andrei Alexandrescu wrote:On 12/10/11 4:31 PM, kenji hara wrote:Yes, but in C++ const is not transitive, so this change necessarily introduces some inconsistency. (for the better, I think) struct S{int* x;} void foo(T)(T t){ ... } immutable int x; foo(immutable(S)(&x)); // deduced type needs to be immutable(S)Treating whole constant arrays as ranges by automatically shedding the top-level const is good. But realizing it by language semantic change is definitely bad.It breaks IFTI rule, and adding special case will make difficult to learn language. Instead of language change, we can add specializations that receive non-ranges and convert them to ranges by removing top-level const. I believe that it is Phobos issue and is never the issue of language.I should add there is precedent. C++ also removes top-level const when passing objects by value to templates. Deducing top-level const with pass-by-value is inherently nonsensical. Andrei
Dec 10 2011
OK. I agree to the suggestion. I've been afraid that increasing IFTI rule is making the language learning difficult. It comes from the experience from implementing inout deduction for template function. But also it is useful that removing top const when passing arguments by val= ue. C++ precedent convinced me. Thanks. Kenji Hara 2011/12/11 kenji hara <k.hara.pg gmail.com>:2011/12/11 Andrei Alexandrescu <SeeWebsiteForEmail erdani.org>:t * to intOn 12/10/11 4:31 PM, kenji hara wrote:Hmm, it's for sure. ---- void print_type(int){} template <typename T> void f(T p) { =A0 =A0int n; =A0 =A0p =3D &n; =A0 =A0 // OK, head is mutable =A0 =A0//*p =3D 10; =A0// NG, tail is const =A0 =A0print_type(p); =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0// Error: need explicit cast from int cons=Treating whole constant arrays as ranges by automatically shedding the top-level const is good. But realizing it by language semantic change is definitely bad.It breaks IFTI rule, and adding special case will make difficult to learn language. Instead of language change, we can add specializations that receive non-ranges and convert them to ranges by removing top-level const. I believe that it is Phobos issue and is never the issue of language.I should add there is precedent. C++ also removes top-level const when passing objects by value to templates. Deducing top-level const with pass-by-value is inherently nonsensical. Andrei=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0// T is deduced as int const * =3D=3D top =const is removed} int main() { =A0 =A0int n; =A0 =A0int const * const p =3D &n; =A0 =A0f(p); =A0 =A0return 0; } Kenji
Dec 10 2011
Posted a test patch to realize the suggestion. https://github.com/D-Programming-Language/dmd/pull/554 Kenji Hara 2011/12/11 kenji hara <k.hara.pg gmail.com>:OK. I agree to the suggestion. I've been afraid that increasing IFTI rule is making the language learning difficult. It comes from the experience from implementing inout deduction for template function. But also it is useful that removing top const when passing arguments by v=alue.C++ precedent convinced me. Thanks. Kenji Hara 2011/12/11 kenji hara <k.hara.pg gmail.com>:st * to int2011/12/11 Andrei Alexandrescu <SeeWebsiteForEmail erdani.org>:On 12/10/11 4:31 PM, kenji hara wrote:Hmm, it's for sure. ---- void print_type(int){} template <typename T> void f(T p) { =A0 =A0int n; =A0 =A0p =3D &n; =A0 =A0 // OK, head is mutable =A0 =A0//*p =3D 10; =A0// NG, tail is const =A0 =A0print_type(p); =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0// Error: need explicit cast from int con=Treating whole constant arrays as ranges by automatically shedding the top-level const is good. But realizing it by language semantic change is definitely bad.It breaks IFTI rule, and adding special case will make difficult to learn language. Instead of language change, we can add specializations that receive non-ranges and convert them to ranges by removing top-level const. I believe that it is Phobos issue and is never the issue of language.I should add there is precedent. C++ also removes top-level const when passing objects by value to templates. Deducing top-level const with pass-by-value is inherently nonsensical. Andreiconst is removed=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0// T is deduced as int const * =3D=3D top=} int main() { =A0 =A0int n; =A0 =A0int const * const p =3D &n; =A0 =A0f(p); =A0 =A0return 0; } Kenji
Dec 10 2011
On 12/10/11 6:24 PM, kenji hara wrote:Posted a test patch to realize the suggestion. https://github.com/D-Programming-Language/dmd/pull/554 Kenji HaraMany thanks, Kenji, for executing so fast on this! Andrei
Dec 10 2011
kenji hara:It breaks IFTI rule,What do you mean?and adding special case will make difficult to learn language.I think that change proposed by Andrei A. (that I like) doesn't add a special case to D2. Currently (2.057beta) this works: void main() { immutable(int[]) a = [1, 2]; immutable(int)[] b = a; } Calling a function that accepts a immutable(int)[] with a immutable(int[]) means creating a local slice, it's similar. So I think Andrei A. removes a special case. Bye, bearophile
Dec 10 2011
2011/12/11 bearophile <bearophileHUGS lycos.com>:kenji hara:I mean following code comment will not become true. void func(T)(T prm){} void main(){ X arg; func(arg); // T is deduced to typeof(arg) }It breaks IFTI rule,What do you mean?cial case to D2. Currently (2.057beta) this works:and adding special case will make difficult to learn language.I think that change proposed by Andrei A. (that I like) doesn't add a spe=void main() { =A0 =A0immutable(int[]) a =3D [1, 2]; =A0 =A0immutable(int)[] b =3D a; } Calling a function that accepts a immutable(int)[] with a immutable(int[]=) means creating a local slice, it's similar. So I think Andrei A. removes = a special case.Bye, bearophile
Dec 10 2011
On Sunday, December 11, 2011 08:01:57 kenji hara wrote:2011/12/11 bearophile <bearophileHUGS lycos.com>:Why does that matter? What does it affect? As far as functions go, it means that immutable str = "hello"; func(str); would instantiate to func!string instead of func!(immutable string) which will no affect on the internals of the function except for the fact that it's no possible to alter the function parameter. The contents of the array are immutable regardless. In what situation would it matter that it's now func!string instead of func! (immutable string)? - Jonathan M Daviskenji hara:I mean following code comment will not become true. void func(T)(T prm){} void main(){ X arg; func(arg); // T is deduced to typeof(arg) }It breaks IFTI rule,What do you mean?
Dec 10 2011
On Sunday, December 11, 2011 07:31:28 kenji hara wrote:Treating whole constant arrays as ranges by automatically shedding the top-level const is good. But realizing it by language semantic change is definitely bad.It breaks IFTI rule, and adding special case will make difficult to learn language. Instead of language change, we can add specializations that receive non-ranges and convert them to ranges by removing top-level const. I believe that it is Phobos issue and is never the issue of language.Making the fix in Phobos is a pain in that you have to duplicate functions all over the place (though they'd just be wrappers, so you wouldn't have to duplicate their implementations). And everyone who defines their own range- based functions have to do the same thing. The question is whether we actually lose anything by making it so that so that IFTI won't give you a fully immutable or const array. And I don't see anything that you'd lose or how it could break any code. Sure, it then becomes possible to alter the array within the function where it wasn't before, but if it couldn't before, making it possible now won't break anything, since the function would have to be changed to even try. And for new functions, if they _really_ want the array to be const or immutable, they can assign it to a new array locally. I don't see how any expressiveness is really lost here or that anything would be broken. So, while this _does_ change the language's semantics, it seems to me that it just changes them for the better, not worse. Making this sort of change for static arrays _would_ be a problem, but I don't see how it's an issue for dynamic arrays. - Jonathan M Davis
Dec 10 2011
On 2011-12-10 21:47:13 +0000, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> said:We decided to fix this issue by automatically shedding the top-level const when passing an array or a pointer by value into a function.It seems strange that if you implemented the exact same semantic as an a dynamic array or a pointer with a struct it wouldn't work. Basically, you're making a special case by giving two language-defined types characteristics that can't be replicated by user types. I'm not concerned that much, but I thought you worried about those things Andrei. Also seems strange to me that class references aren't included in that list, but then I though about how tail-const still doesn't work with objects. You'd need my const(Object)ref patch to make that work, and Walter hasn't taken time to look at it yet… -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Dec 10 2011
On 12/10/11 5:20 PM, Michel Fortin wrote:On 2011-12-10 21:47:13 +0000, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> said:I do worry about those things, and this decision comes at the end of a long deliberation. There would be several aspects to discuss here. First, you are right that this confers built-in arrays a property that's not reproducible to user-defined types. And that's a bad thing. Second, that's not really as bad because the real issue is elsewhere. Remember the type "new T[]"? That was supposed to be the array type, which was to be supplanted by its range type, "T[]". After experimentation we decided to give up on that. Why? Because its benefits didn't justify the complication. So the issue we're solving here is that arrays and the ranges that crawl on them are represented by the same type. User-defined types have the option of defining distinct types for that. To truly confer user-defined types the same capability, we should define opPassByValue() which is implicitly invoked whenever an object is passed by value into a function. By default that is a do-nothing operator; for arrays it would do the cast thing (or, equivalently, invoke "[]" on the array), and people could define it to do whatever. We could do all that. The question is, is the added complexity justified?We decided to fix this issue by automatically shedding the top-level const when passing an array or a pointer by value into a function.It seems strange that if you implemented the exact same semantic as an a dynamic array or a pointer with a struct it wouldn't work. Basically, you're making a special case by giving two language-defined types characteristics that can't be replicated by user types. I'm not concerned that much, but I thought you worried about those things Andrei.Also seems strange to me that class references aren't included in that list, but then I though about how tail-const still doesn't work with objects. You'd need my const(Object)ref patch to make that work, and Walter hasn't taken time to look at it yet…Have you continued to use your fork in daily work? If so, how does it pan out? Andrei
Dec 10 2011
On Sunday, December 11, 2011 01:16:28 Andrei Alexandrescu wrote:On 12/10/11 5:20 PM, Michel Fortin wrote:I think that it's completely justified. We need a way to define tail-constness for ranges. Given const's transitiveness, it's very easy to end up in a situation where you have a const range, and having a means to get a tail-const version of that range would be very valuable. I don't know if opPassByValue is the best solution, but if not, we at least need a similar one. I'd say that in general, with opPassByValue, in the worst case, some people don't use it for their range types and those ranges don't work properly in cases that require tail-const. But those people who _do_ use it can benefit from it. It doesn't force anything on anyone. Yes, it's one more thing to learn about know about in D, but it _is_ something that a number of us have cited a need for for a while. - Jonathan M DavisOn 2011-12-10 21:47:13 +0000, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> said:I do worry about those things, and this decision comes at the end of a long deliberation. There would be several aspects to discuss here. First, you are right that this confers built-in arrays a property that's not reproducible to user-defined types. And that's a bad thing. Second, that's not really as bad because the real issue is elsewhere. Remember the type "new T[]"? That was supposed to be the array type, which was to be supplanted by its range type, "T[]". After experimentation we decided to give up on that. Why? Because its benefits didn't justify the complication. So the issue we're solving here is that arrays and the ranges that crawl on them are represented by the same type. User-defined types have the option of defining distinct types for that. To truly confer user-defined types the same capability, we should define opPassByValue() which is implicitly invoked whenever an object is passed by value into a function. By default that is a do-nothing operator; for arrays it would do the cast thing (or, equivalently, invoke "[]" on the array), and people could define it to do whatever. We could do all that. The question is, is the added complexity justified?We decided to fix this issue by automatically shedding the top-level const when passing an array or a pointer by value into a function.It seems strange that if you implemented the exact same semantic as an a dynamic array or a pointer with a struct it wouldn't work. Basically, you're making a special case by giving two language-defined types characteristics that can't be replicated by user types. I'm not concerned that much, but I thought you worried about those things Andrei.
Dec 10 2011
On 12/11/11 1:30 AM, Jonathan M Davis wrote:On Sunday, December 11, 2011 01:16:28 Andrei Alexandrescu wrote:I'm not sure. How many times have you been in a place in life where you had a const range on your hands, that's not an array? I haven't. AndreiTo truly confer user-defined types the same capability, we should define opPassByValue() which is implicitly invoked whenever an object is passed by value into a function. By default that is a do-nothing operator; for arrays it would do the cast thing (or, equivalently, invoke "[]" on the array), and people could define it to do whatever. We could do all that. The question is, is the added complexity justified?I think that it's completely justified. We need a way to define tail-constness for ranges. Given const's transitiveness, it's very easy to end up in a situation where you have a const range, and having a means to get a tail-const version of that range would be very valuable. I don't know if opPassByValue is the best solution, but if not, we at least need a similar one.
Dec 11 2011
On 12/11/2011 12:05 AM, Andrei Alexandrescu wrote:I'm not sure. How many times have you been in a place in life where you had a const range on your hands, that's not an array? I haven't. AndreiHmmm.. isn't that precisely what happens when you define a 'const' method for your (custom) range type? 'this' now becomes a const range.
Dec 11 2011
On 12/11/11 2:08 AM, Mehrdad wrote:On 12/11/2011 12:05 AM, Andrei Alexandrescu wrote:What do you do inside that method? It's reasonable to not expect to change it. AndreiI'm not sure. How many times have you been in a place in life where you had a const range on your hands, that's not an array? I haven't. AndreiHmmm.. isn't that precisely what happens when you define a 'const' method for your (custom) range type? 'this' now becomes a const range.
Dec 11 2011
On 12/11/2011 12:14 AM, Andrei Alexandrescu wrote:What do you do inside that method? It's reasonable to not expect to change it. AndreiNot sure right now, but something along the lines of auto copy = this; foreach (v; copy) ....; sounds like code I've definitely seen before.
Dec 11 2011
On 12/11/11 2:36 AM, Mehrdad wrote:On 12/11/2011 12:14 AM, Andrei Alexandrescu wrote:I think you should write: auto copy = this.save; AndreiWhat do you do inside that method? It's reasonable to not expect to change it. AndreiNot sure right now, but something along the lines of auto copy = this; foreach (v; copy) ....; sounds like code I've definitely seen before.
Dec 11 2011
On 12/11/2011 12:57 AM, Andrei Alexandrescu wrote:I think you should write: auto copy = this.save; AndreiAh good point, I forgot about that. Idk then. (You forgot the parentheses though. :P)
Dec 11 2011
On 12/11/2011 1:04 AM, Mehrdad wrote:On 12/11/2011 12:57 AM, Andrei Alexandrescu wrote:Try the new beta http://ftp.digitalmars.com/dmd2beta.zipI think you should write: auto copy = this.save; AndreiAh good point, I forgot about that. Idk then. (You forgot the parentheses though. :P)
Dec 11 2011
On 12/11/2011 1:54 AM, Walter Bright wrote:Try the new beta http://ftp.digitalmars.com/dmd2beta.zipWHOA nice, the reduce() example worked!! :D Thanks for taking the time to fix it! I'll post if I come across similar/related problems. :)
Dec 11 2011
On 12/11/11 10:04 AM, Mehrdad wrote:On 12/11/2011 12:57 AM, Andrei Alexandrescu wrote:No, it's correct like that, save() is a property. Even though I recently updated Phobos to compile with -property enabled, I agree with Andrei here that in many cases there will be no perfect consensus whether a given member should be a property or not, thus potentially adding an extra source of complexity, or rather annoyance. DavidI think you should write: auto copy = this.save;Ah good point, I forgot about that. Idk then. (You forgot the parentheses though. :P)
Dec 11 2011
On 12/11/2011 2:56 AM, David Nadlinger wrote:On 12/11/11 10:04 AM, Mehrdad wrote:Whoa what?! I didn't know save() is a property. In that case I stand corrected. :-) Nevertheless, I think that makes no sense. :P If something isn't a "property" of something else, it shouldn't be marked as such. But there are more reasons than that... of the word property: http://msdn.microsoft.com/en-us/library/ms182181.aspx Specifically: "Properties should behave as if they are fields; if the method cannot, it should not be changed to a property. Methods are better than properties in the following situations: - Calling the method two times in succession creates different results. - The method performs a time-consuming operation. The method is perceivably slower than the time that is required to set or get the value of a field." Since both of these can be true for all but the most trivial kinds of ranges (e.g. file-system-related enumerators/ranges would very likely need to re-open a handle to a directory in order to traverse it, which is both relatively time-consuming AND returns a different result every time, and could even unexpectedly fail due to permission/connectivity issues), I don't think it makes sense for save() to be a property.On 12/11/2011 12:57 AM, Andrei Alexandrescu wrote:No, it's correct like that, save() is a property. Even though I recently updated Phobos to compile with -property enabled, I agree with Andrei here that in many cases there will be no perfect consensus whether a given member should be a property or not, thus potentially adding an extra source of complexity, or rather annoyance. DavidI think you should write: auto copy = this.save;Ah good point, I forgot about that. Idk then. (You forgot the parentheses though. :P)
Dec 11 2011
Specifically: "Properties should behave as if they are fields; if the method cannot, it should not be changed to a property. Methods are better than properties in the following situations: - Calling the method two times in succession creates different results. - The method performs a time-consuming operation. The method is perceivably slower than the time that is required to set or get the value of a field." Since both of these can be true for all but the most trivial kinds of ranges (e.g. file-system-related enumerators/ranges would very likely need to re-open a handle to a directory in order to traverse it, which is both relatively time-consuming AND returns a different result every time, and could even unexpectedly fail due to permission/connectivity issues), I don't think it makes sense for save() to be a property.I agree.
Dec 11 2011
On Sunday, December 11, 2011 14:54:27 Tobias Pankrath wrote:It was debated some time ago, and it ended up being a property. The fact that save is an action verb and not a noun automatically disqualifies it as a property IMHO, but it was made into a property, and we're pretty much stuck with it at some point. As far as what the function does, I don't think that it's a problem that it's a property, but it's not named like a property, so the situation with regards to save is not ideal, but it's too late now. - Jonathan M DavisSpecifically: "Properties should behave as if they are fields; if the method cannot, it should not be changed to a property. Methods are better than properties in the following situations: - Calling the method two times in succession creates different results. - The method performs a time-consuming operation. The method is perceivably slower than the time that is required to set or get the value of a field." Since both of these can be true for all but the most trivial kinds of ranges (e.g. file-system-related enumerators/ranges would very likely need to re-open a handle to a directory in order to traverse it, which is both relatively time-consuming AND returns a different result every time, and could even unexpectedly fail due to permission/connectivity issues), I don't think it makes sense for save() to be a property.I agree.
Dec 11 2011
On 12/11/2011 11:24 PM, Jonathan M Davis wrote:On Sunday, December 11, 2011 14:54:27 Tobias Pankrath wrote:Reminds me of .NET's Object.GetHashCode() method, which should be a property according to their guide. Another is Object.GetType() - why is it not a property anyway? Both are supposed to return the same value on succesive calls and both are computationally cheap. Other examples are widget size setters that can be computationally quite expensive (resizing child widgets, etc.). They are usually property setters regardless of the fact that they are "perceivably slower" to set than fields.It was debated some time ago, and it ended up being a property. The fact that save is an action verb and not a noun automatically disqualifies it as a property IMHO, but it was made into a property, and we're pretty much stuck with it at some point. As far as what the function does, I don't think that it's a problem that it's a property, but it's not named like a property, so the situation with regards to save is not ideal, but it's too late now. - Jonathan M DavisSpecifically: "Properties should behave as if they are fields; if the method cannot, it should not be changed to a property. Methods are better than properties in the following situations: - Calling the method two times in succession creates different results. - The method performs a time-consuming operation. The method is perceivably slower than the time that is required to set or get the value of a field." Since both of these can be true for all but the most trivial kinds of ranges (e.g. file-system-related enumerators/ranges would very likely need to re-open a handle to a directory in order to traverse it, which is both relatively time-consuming AND returns a different result every time, and could even unexpectedly fail due to permission/connectivity issues), I don't think it makes sense for save() to be a property.I agree.
Dec 12 2011
On 11.12.2011 22:24, Jonathan M Davis wrote: ...It was debated some time ago, and it ended up being a property. The fact that save is an action verb and not a noun automatically disqualifies it as a property IMHO, but it was made into a property, and we're pretty much stuck with it at some point. As far as what the function does, I don't think that it's a problem that it's a property, but it's not named like a property, so the situation with regards to save is not ideal, but it's too late now.I really don't get this. When D has 10,000 programmers using it professionally, it's too late. But now it's more like 5 or 10. And they are all presumably aware that D2 is still undergoing some polish. So are the maybe a few hundred people that are using D for hobby projects. They are early adopters, and they know what that entails. I call bogus on the backwards compatibility argument. There's not a lot to be compatible with at this stage. Not compared to what D2 wants to become. As for Andrei's book using save with the parentheses: If D2 gains traction, I'm sure there will be a second edition of that book. And you already want to have the errata handy when using the book. I don't see what the big deal is, at least not compared to letting this stay in the language forever. save being a property is a stupid inconsistency. It's easy to fix, the cost is relatively low. The people using D2 now are all part of a community that want D to succeed, as am I. It's a change for the better, which I'm sure most current D2 users would agree with. How hard can it be?
Dec 12 2011
On Monday, 12 December 2011 at 12:24:53 UTC, torhu wrote:On 11.12.2011 22:24, Jonathan M Davis wrote: ...Furthermore, there weren't even a way to enforce the property syntax until lately, and it's still not enabled by default. If we change it right now, people still have time to adapt before the backwards-compatibility argument even kicks in (no matter how weak it is).It was debated some time ago, and it ended up being a property. The fact that save is an action verb and not a noun automatically disqualifies it as a property IMHO, but it was made into a property, and we're pretty much stuck with it at some point. As far as what the function does, I don't think that it's a problem that it's a property, but it's not named like a property, so the situation with regards to save is not ideal, but it's too late now.I really don't get this. When D has 10,000 programmers using it professionally, it's too late. But now it's more like 5 or 10. And they are all presumably aware that D2 is still undergoing some polish. So are the maybe a few hundred people that are using D for hobby projects. They are early adopters, and they know what that entails. I call bogus on the backwards compatibility argument. There's not a lot to be compatible with at this stage. Not compared to what D2 wants to become. As for Andrei's book using save with the parentheses: If D2 gains traction, I'm sure there will be a second edition of that book. And you already want to have the errata handy when using the book. I don't see what the big deal is, at least not compared to letting this stay in the language forever. save being a property is a stupid inconsistency. It's easy to fix, the cost is relatively low. The people using D2 now are all part of a community that want D to succeed, as am I. It's a change for the better, which I'm sure most current D2 users would agree with. How hard can it be?
Dec 12 2011
On 2011-12-12 12:38:09 +0000, "Jakob Ovrum" <jakobovrum gmail.com> said:Furthermore, there weren't even a way to enforce the property syntax until lately, and it's still not enabled by default. If we change it right now, people still have time to adapt before the backwards-compatibility argument even kicks in (no matter how weak it is).Indeed. As far as we know, there might be more people out there using save as a function than there are using save as a property. We don't know that because it isn't enforced and people will simply use what they feel is best. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Dec 12 2011
On Monday, 12 December 2011 at 12:38:10 UTC, Jakob Ovrum wrote:Furthermore, there weren't even a way to enforce the property syntax until lately, and it's still not enabled by default.The real WTF is that someone decided property should be used for anything more than disambiguation.
Dec 12 2011
On 12 December 2011 14:24, torhu <no spam.invalid> wrote:On 11.12.2011 22:24, Jonathan M Davis wrote: ... It was debated some time ago, and it ended up being a property. The factI completely agree. One thing that most excited me about D at this stage, and buying in as an early adopter is that the developers WILL have the courage to make breaking changes if they're in the interest of creating a better language. I think every opportunity should be taken to make important breaking changes while the community is as small as it is. If the changes are reasonably trivial, then surely it doesn't trouble anyone THAT much to update their code. If they're using D2, surely they know it's still in the works.that save is an action verb and not a noun automatically disqualifies it as a property IMHO, but it was made into a property, and we're pretty much stuck with it at some point. As far as what the function does, I don't think that it's a problem that it's a property, but it's not named like a property, so the situation with regards to save is not ideal, but it's too late now.I really don't get this. When D has 10,000 programmers using it professionally, it's too late. But now it's more like 5 or 10. And they are all presumably aware that D2 is still undergoing some polish. So are the maybe a few hundred people that are using D for hobby projects. They are early adopters, and they know what that entails. I call bogus on the backwards compatibility argument. There's not a lot to be compatible with at this stage. Not compared to what D2 wants to become. As for Andrei's book using save with the parentheses: If D2 gains traction, I'm sure there will be a second edition of that book. And you already want to have the errata handy when using the book. I don't see what the big deal is, at least not compared to letting this stay in the language forever. save being a property is a stupid inconsistency. It's easy to fix, the cost is relatively low. The people using D2 now are all part of a community that want D to succeed, as am I. It's a change for the better, which I'm sure most current D2 users would agree with. How hard can it be?
Dec 12 2011
On 12/12/11 6:49 AM, Manu wrote:I think every opportunity should be taken to make important breaking changes while the community is as small as it is.Changing from r.save to r.save() is NOT an important change. It makes no semantic difference, marks no progress, and has no consequence. Insisting on the current property semantics was a sizeable mistake of this community, and I am sorry we gave into it. Andrei
Dec 12 2011
On Monday, 12 December 2011 at 14:46:17 UTC, Andrei Alexandrescu wrote:On 12/12/11 6:49 AM, Manu wrote:The whole point of a property to begin with is to make it look like a field, which has two important implications: improves interchangeability with function access vs a field, and exploits the user's intuition associated with accessing fields. It is in light of the second consequence that it makes a difference. This is nothing new; the style guides for properties access, it should behave like field access. If the programmer sees just "r.save", he doesn't know whether it's a field or a property, and he shouldn't need to know, it should be fast and cheap, and return a consistent value. As far as I know, this isn't always true for save, which means it breaks with the user's intuition. I don't know whether or not this is an important change, but it *does* have consequence, and the current property semantics (as enforced with -property) are definitely meaningful. The old situation where you could write complete nonsense code like `std.file.read = "foo.txt";` is far worse.I think every opportunity should be taken to make important breaking changes while the community is as small as it is.Changing from r.save to r.save() is NOT an important change. It makes no semantic difference, marks no progress, and has no consequence. Insisting on the current property semantics was a sizeable mistake of this community, and I am sorry we gave into it. Andrei
Dec 12 2011
On 12/12/11 9:07 AM, Jakob Ovrum wrote:If the programmer sees just "r.save", he doesn't know whether it's a field or a property, and he shouldn't need to know, it should be fast and cheap, and return a consistent value. As far as I know, this isn't always true for saveWhy? Save does behave like a field for the vast majority of structs. Andrei
Dec 12 2011
On Monday, 12 December 2011 at 15:14:02 UTC, Andrei Alexandrescu wrote:On 12/12/11 9:07 AM, Jakob Ovrum wrote:But save is an abstract interface function, its signature should reflect all possible implementations.If the programmer sees just "r.save", he doesn't know whether it's a field or a property, and he shouldn't need to know, it should be fast and cheap, and return a consistent value. As far as I know, this isn't always true for saveWhy? Save does behave like a field for the vast majority of structs. Andrei
Dec 12 2011
On 12/12/2011 04:29 PM, Jakob Ovrum wrote:On Monday, 12 December 2011 at 15:14:02 UTC, Andrei Alexandrescu wrote:Under the premise that a function should be a property iff it behaves like a field, that is impossible.On 12/12/11 9:07 AM, Jakob Ovrum wrote:But save is an abstract interface function, its signature should reflect all possible implementations.If the programmer sees just "r.save", he doesn't know whether it's a field or a property, and he shouldn't need to know, it should be fast and cheap, and return a consistent value. As far as I know, this isn't always true for saveWhy? Save does behave like a field for the vast majority of structs. Andrei
Dec 12 2011
On Monday, 12 December 2011 at 15:29:26 UTC, Jakob Ovrum wrote:On Monday, 12 December 2011 at 15:14:02 UTC, Andrei Alexandrescu wrote:Adding on this: I have no problem with save being a property if it's meant/designed to be cheap etc. like with most struct ranges and slices. I also don't think the name is a problem; if you want to be really pedantic, "save" is actually a noun as well :POn 12/12/11 9:07 AM, Jakob Ovrum wrote:But save is an abstract interface function, its signature should reflect all possible implementations.If the programmer sees just "r.save", he doesn't know whether it's a field or a property, and he shouldn't need to know, it should be fast and cheap, and return a consistent value. As far as I know, this isn't always true for saveWhy? Save does behave like a field for the vast majority of structs. Andrei
Dec 12 2011
On 12/12/11 9:29 AM, Jakob Ovrum wrote:On Monday, 12 December 2011 at 15:14:02 UTC, Andrei Alexandrescu wrote:Same goes for many properties. AndreiOn 12/12/11 9:07 AM, Jakob Ovrum wrote:But save is an abstract interface function, its signature should reflect all possible implementations.If the programmer sees just "r.save", he doesn't know whether it's a field or a property, and he shouldn't need to know, it should be fast and cheap, and return a consistent value. As far as I know, this isn't always true for saveWhy? Save does behave like a field for the vast majority of structs. Andrei
Dec 12 2011
On Monday, 12 December 2011 at 16:09:03 UTC, Andrei Alexandrescu wrote:On 12/12/11 9:29 AM, Jakob Ovrum wrote:This is true, and many functions marked property arguably shouldn't be. I think it's a little like the reason std.container.SList doesn't have a `length` property: the O(n) complexity doesn't match the interface `length` exposes (although formalised only in documentation/convention, not code). If the standard library is allowed to assume `r.save` is a cheap operation, in the same fashion it's allowed to assume this(this) is cheap, then by all means, it makes sense as a property. The only remaining arguments against it are purely about the name, and I actually don't think that's relevant. And just like you can still make a computationally expensive this(this) when absolutely necessary, you can do the same with save. If most reasonable uses of save have trivial performance, it might as well be a property. I'm still a beginner with ranges, but by my understanding and by what some people made it sound like, reasonable uses of save include some which are non-trivial. If this is true, then removing property from save encourages people to think more about what using it might mean for the code they are writing, which is definitely important.On Monday, 12 December 2011 at 15:14:02 UTC, Andrei Alexandrescu wrote:Same goes for many properties. AndreiOn 12/12/11 9:07 AM, Jakob Ovrum wrote:But save is an abstract interface function, its signature should reflect all possible implementations.If the programmer sees just "r.save", he doesn't know whether it's a field or a property, and he shouldn't need to know, it should be fast and cheap, and return a consistent value. As far as I know, this isn't always true for saveWhy? Save does behave like a field for the vast majority of structs. Andrei
Dec 12 2011
On Monday, December 12, 2011 17:24:38 Jakob Ovrum wrote:I'm still a beginner with ranges, but by my understanding and by what some people made it sound like, reasonable uses of save include some which are non-trivial. If this is true, then removing property from save encourages people to think more about what using it might mean for the code they are writing, which is definitely important.Both save and postblit are supposed to be trivial. Algorithms generally assume that copying a range is O(1). There's nothing stopping save and postblit from costing more than that, but it's going to harm performance. - Jonathan M Davis
Dec 12 2011
On Monday, 12 December 2011 at 15:07:16 UTC, Jakob Ovrum wrote:The old situation where you could write complete nonsense code like `std.file.read = "foo.txt";` is far worse.If we start removing features because someone can use them when deliberately obfuscating their code, we might as well just abandon the whole idea of programming languages.
Dec 12 2011
On Monday, 12 December 2011 at 15:16:56 UTC, Adam D. Ruppe wrote:On Monday, 12 December 2011 at 15:07:16 UTC, Jakob Ovrum wrote:Firstly, no feature is removed, it is changed, unless you consider calling completely property-unrelated functions with this syntax a feature. Secondly, it is an extreme example, more commonly occurring examples would be conflating property access with calling a member function with non-trivial complexity. With enforced property, the compiler helps the user write the most readable code for himself and more importantly, others.The old situation where you could write complete nonsense code like `std.file.read = "foo.txt";` is far worse.If we start removing features because someone can use them when deliberately obfuscating their code, we might as well just abandon the whole idea of programming languages.
Dec 12 2011
On 12/12/11 9:07 AM, Jakob Ovrum wrote:The old situation where you could write complete nonsense code like `std.file.read = "foo.txt";` is far worse.We could have defined a system much better than both. Andrei
Dec 12 2011
On Monday, 12 December 2011 at 15:21:31 UTC, Andrei Alexandrescu wrote:On 12/12/11 9:07 AM, Jakob Ovrum wrote:I definitely agree. I think the current situation sucks. But I also think the previous situation sucks much, much more. (Unrelated side-note: I am using the web interface and I'm not well seasoned with using newsgroups, is there a better way to reply to multiple small posts than replying to each individually like I just did? I apologize if I'm being spammy.)The old situation where you could write complete nonsense code like `std.file.read = "foo.txt";` is far worse.We could have defined a system much better than both. Andrei
Dec 12 2011
On Monday, 12 December 2011 at 15:32:05 UTC, Jakob Ovrum wrote:(Unrelated side-note: I am using the web interface and I'm not well seasoned with using newsgroups, is there a better way to reply to multiple small posts than replying to each individually like I just did? I apologize if I'm being spammy.)I don't think that's a problem. But to answer your question, no. The next best thing is to reply to the posts' common parent, or the thread's first post. Cite authors preserving the name/timestamp line and relevant quoted context.
Dec 13 2011
On Monday, December 12, 2011 08:46:18 Andrei Alexandrescu wrote:Insisting on the current property semantics was a sizeable mistake of this community, and I am sorry we gave into it.Aside from the fact that the behavior of -property isn't the default, what's the problem with property? - Jonathan M Davis
Dec 12 2011
On 12/12/11 1:12 PM, Jonathan M Davis wrote:On Monday, December 12, 2011 08:46:18 Andrei Alexandrescu wrote:Other than it being completely useless, requiring more rote memorization, and fomenting time-wasting discussion? None. AndreiInsisting on the current property semantics was a sizeable mistake of this community, and I am sorry we gave into it.Aside from the fact that the behavior of -property isn't the default, what's the problem with property?
Dec 12 2011
On Mon, 12 Dec 2011 19:00:35 -0500, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:On 12/12/11 1:12 PM, Jonathan M Davis wrote:Wait, are we talking about property or .save? -SteveOn Monday, December 12, 2011 08:46:18 Andrei Alexandrescu wrote:Other than it being completely useless, requiring more rote memorization, and fomenting time-wasting discussion? None.Insisting on the current property semantics was a sizeable mistake of this community, and I am sorry we gave into it.Aside from the fact that the behavior of -property isn't the default, what's the problem with property?
Dec 12 2011
On 12/13/2011 01:08 AM, Steven Schveighoffer wrote:On Mon, 12 Dec 2011 19:00:35 -0500, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:definitely property.On 12/12/11 1:12 PM, Jonathan M Davis wrote:Wait, are we talking about property or .save? -SteveOn Monday, December 12, 2011 08:46:18 Andrei Alexandrescu wrote:Other than it being completely useless, requiring more rote memorization, and fomenting time-wasting discussion? None.Insisting on the current property semantics was a sizeable mistake of this community, and I am sorry we gave into it.Aside from the fact that the behavior of -property isn't the default, what's the problem with property?
Dec 13 2011
On Monday, December 12, 2011 18:00:35 Andrei Alexandrescu wrote:On 12/12/11 1:12 PM, Jonathan M Davis wrote:So, you prefer the situation where any function with no arguments can be used as a getter and any function with a single argument can be used as a setter? Not only is that incredibly lax, but it makes it impossible to be able to switch between public member variables and property functions without breaking code, which is supposed to be one of the main purposes of property functions in programming languages in general. With property, such a switch _is_ possible (aside from a few corner cases such as when someone takes the address of a public member variable). It will also lead to a consistent use of parentheses instead of having the syntax used with a function varying wherever it's used. Sure, you then get arguments over whether a function should be a property or not, but that's generally just part of the discussion of how to name a function, and with that, there's always risk that someone will disagree later, so I'm not sure that it makes the situation all that much worse, and IMHO it's well worth the advantage of having proper properties. What D had was better than nothing, but it was inconsistent and lacked the ability to swap member variables and property functions, which made it far worse than property IMHO. - Jonathan M DavisOn Monday, December 12, 2011 08:46:18 Andrei Alexandrescu wrote:Other than it being completely useless, requiring more rote memorization, and fomenting time-wasting discussion? None.Insisting on the current property semantics was a sizeable mistake of this community, and I am sorry we gave into it.Aside from the fact that the behavior of -property isn't the default, what's the problem with property?
Dec 13 2011
On 12/13/11 10:32 AM, Jonathan M Davis wrote:On Monday, December 12, 2011 18:00:35 Andrei Alexandrescu wrote:No. That would be a false choice. AndreiOn 12/12/11 1:12 PM, Jonathan M Davis wrote:So, you prefer the situation where any function with no arguments can be used as a getter and any function with a single argument can be used as a setter?On Monday, December 12, 2011 08:46:18 Andrei Alexandrescu wrote:Other than it being completely useless, requiring more rote memorization, and fomenting time-wasting discussion? None.Insisting on the current property semantics was a sizeable mistake of this community, and I am sorry we gave into it.Aside from the fact that the behavior of -property isn't the default, what's the problem with property?
Dec 13 2011
On Tuesday, December 13, 2011 14:02:51 Andrei Alexandrescu wrote:On 12/13/11 10:32 AM, Jonathan M Davis wrote:I'm not saying that those are the only choices, but you seem to think that the current situation is worse than what we had before, which I don't understand. The current situation looks all around better to me. - Jonathan M DavisOn Monday, December 12, 2011 18:00:35 Andrei Alexandrescu wrote:No. That would be a false choice.On 12/12/11 1:12 PM, Jonathan M Davis wrote:So, you prefer the situation where any function with no arguments can be used as a getter and any function with a single argument can be used as a setter?On Monday, December 12, 2011 08:46:18 Andrei Alexandrescu wrote:Other than it being completely useless, requiring more rote memorization, and fomenting time-wasting discussion? None.Insisting on the current property semantics was a sizeable mistake of this community, and I am sorry we gave into it.Aside from the fact that the behavior of -property isn't the default, what's the problem with property?
Dec 13 2011
On 12/13/11 2:25 PM, Jonathan M Davis wrote:On Tuesday, December 13, 2011 14:02:51 Andrei Alexandrescu wrote:There's a phrase in Romanian that quite applies: "From the lake into the well". AndreiOn 12/13/11 10:32 AM, Jonathan M Davis wrote:I'm not saying that those are the only choices, but you seem to think that the current situation is worse than what we had before, which I don't understand. The current situation looks all around better to me.On Monday, December 12, 2011 18:00:35 Andrei Alexandrescu wrote:No. That would be a false choice.On 12/12/11 1:12 PM, Jonathan M Davis wrote:So, you prefer the situation where any function with no arguments can be used as a getter and any function with a single argument can be used as a setter?On Monday, December 12, 2011 08:46:18 Andrei Alexandrescu wrote:Other than it being completely useless, requiring more rote memorization, and fomenting time-wasting discussion? None.Insisting on the current property semantics was a sizeable mistake of this community, and I am sorry we gave into it.Aside from the fact that the behavior of -property isn't the default, what's the problem with property?
Dec 13 2011
On Tuesday, 13 December 2011 at 21:10:22 UTC, Andrei Alexandrescu wrote:There's a phrase in Romanian that quite applies: "From the lake into the well".I believe the English version is "Out of the frying pan, into the fire" :) Inconsequential space-filler opinion: I am OK with property, mainly because it's a common feature among PLs, it's better than nothing, and don't know better solutions.
Dec 13 2011
On 13/12/11 10:17 PM, Vladimir Panteleev wrote:On Tuesday, 13 December 2011 at 21:10:22 UTC, Andrei Alexandrescu wrote:In my opinion, it's not better than nothing. What it gives you: 1. A bit of syntactic sugar. 2. The ability to refactor member look up easily. What it costs: 1. Overloads syntax. a. obj.field can now be an arbitrary function call. b. May have arbitrary cost (e.g. T[].length) 2. Complicating the language (proof: this discussion) 3. Another thing to learn. 4. Another thing for tools to process. I don't think the syntax sugar it provides counts for anything really. The ability to refactor member look ups is nice, but I find that this rarely occurs in practice and even when it occurs, it's not hard to replace obj.field with obj.field() or obj.getField(). The costs far outweigh the benefits IMO.There's a phrase in Romanian that quite applies: "From the lake into the well".I believe the English version is "Out of the frying pan, into the fire" :) Inconsequential space-filler opinion: I am OK with property, mainly because it's a common feature among PLs, it's better than nothing, and don't know better solutions.
Dec 13 2011
On 12/13/11 5:14 PM, Peter Alexander wrote:On 13/12/11 10:17 PM, Vladimir Panteleev wrote:We could have inferred property intention from the code pattern, without requiring any keyword. That solution (which was discussed and rejected in this newsgroup) was miles ahead from the drivel of property we have now. I noticed there's a tunnel vision phenomenon when it comes to keyword-based solutions: once a special notation is on the table, there's no appreciation for anything else. That's what happened with lazy (another design misfire I'm very unhappy about) and with property. I literally feel my heart rate getting up when I think of them. AndreiOn Tuesday, 13 December 2011 at 21:10:22 UTC, Andrei Alexandrescu wrote:In my opinion, it's not better than nothing. What it gives you: 1. A bit of syntactic sugar. 2. The ability to refactor member look up easily. What it costs: 1. Overloads syntax. a. obj.field can now be an arbitrary function call. b. May have arbitrary cost (e.g. T[].length) 2. Complicating the language (proof: this discussion) 3. Another thing to learn. 4. Another thing for tools to process. I don't think the syntax sugar it provides counts for anything really. The ability to refactor member look ups is nice, but I find that this rarely occurs in practice and even when it occurs, it's not hard to replace obj.field with obj.field() or obj.getField(). The costs far outweigh the benefits IMO.There's a phrase in Romanian that quite applies: "From the lake into the well".I believe the English version is "Out of the frying pan, into the fire" :) Inconsequential space-filler opinion: I am OK with property, mainly because it's a common feature among PLs, it's better than nothing, and don't know better solutions.
Dec 13 2011
On 2011-12-13 23:08:43 +0000, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> said:We could have inferred property intention from the code pattern, without requiring any keyword. That solution (which was discussed and rejected in this newsgroup) was miles ahead from the drivel of property we have now.By "code patterns", you mean something like this? struct Foo { int getBar(); void setBar(int); } void main() { Foo foo; int a = foo.bar; // calls getBar() foo.bar = a; // calls setBar(a) } I agree it's better. For one thing it'd be much less confusing about whether it make sense to make something a property or not because you'd have to write "get" in front of it -- for instance getSave doesn't make any sense. And it'd be much less problematic too: the way property is currently designed, you can't distinguish between a definition for a an array-member property getter and a module-level property setter. Also with the current design you have no way to disambiguate array-member properties with the same name coming from different modules -- can't replace array.front with std.range.front(array) when property is enforced -- having access to the property's underlying function would mitigate this -- std.range.getFront(array) would still work. The above code pattern would also make it saner to take the address of the getter function as a separate thing from taking the address of a ref value obtained from a property. Personally, I'm skeptical the current property design can work as intended without introducing many issues like the above. I think perhaps the biggest mistake was to not implement it fully from the start at a time where we could easily revert to another proposition if it proved to be problematic. Unfortunately, now we're stuck with property and all its problems… although I'd sure like the design to be revised. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Dec 13 2011
On Tuesday, December 13, 2011 21:36:43 Michel Fortin wrote:On 2011-12-13 23:08:43 +0000, Andrei Alexandrescu =20 <SeeWebsiteForEmail erdani.org> said:ndWe could have inferred property intention from the code pattern, without requiring any keyword. That solution (which was discussed a='drejected in this newsgroup) was miles ahead from the drivel of property we have now.=20 By "code patterns", you mean something like this? =20 =09struct Foo =09{ =09=09int getBar(); =09=09void setBar(int); =09} =20 =09void main() =09{ =09=09Foo foo; =09=09int a =3D foo.bar; // calls getBar() =09=09foo.bar =3D a; // calls setBar(a) =09} =20 I agree it's better. For one thing it'd be much less confusing about whether it make sense to make something a property or not because you=have to write "get" in front of it -- for instance getSave doesn't ma=keany sense. =20 And it'd be much less problematic too: the way property is currently=designed, you can't distinguish between a definition for a an array-member property getter and a module-level property setter. Also=with the current design you have no way to disambiguate array-member properties with the same name coming from different modules -- can't replace array.front with std.range.front(array) when property is enforced -- having access to the property's underlying function woul=dmitigate this -- std.range.getFront(array) would still work. The abov=ecode pattern would also make it saner to take the address of the gett=erfunction as a separate thing from taking the address of a ref value obtained from a property. =20 Personally, I'm skeptical the current property design can work as intended without introducing many issues like the above. I think perhaps the biggest mistake was to not implement it fully from the start at a time where we could easily revert to another proposition i=fit proved to be problematic. Unfortunately, now we're stuck with property and all its problems=E2=80=A6 although I'd sure like the de=sign to berevised.I'd think that some revision would be possible even if it breaks code a= s long=20 as there is great need for it - though that would depend on Walter's de= cision.=20 But since property is in TDPL, a complete redesign wouldn't make sense= =20 without _major_ need. Smaller tweaks wouldn't be as big a deal though. = I'm not=20 quite sure how property would be adjusted for some of these corner cas= es=20 though. The basic idea works well for member functions, but once you ad= d free=20 functions into the mix, it gets more complicated. - Jonathan M Davis
Dec 13 2011
On Wed, 14 Dec 2011 02:36:43 -0000, Michel Fortin = <michel.fortin michelf.com> wrote:On 2011-12-13 23:08:43 +0000, Andrei Alexandrescu =<SeeWebsiteForEmail erdani.org> said:We could have inferred property intention from the code pattern, ==without requiring any keyword. That solution (which was discussed and=rejected in this newsgroup) was miles ahead from the drivel of =struct Foo { int bar // <- does DMD do lookahead? detect { instead of ; here and= = trigger "property" parsing { get { return value; // <- 'value' meaning the value of the 'bar' membe= r } set { this =3D value; // <- 'this' meaning the 'bar' member, 'value' me= aning = the RHS of the "=C2=A3instance.bar =3D <value>" statement } } } Reganproperty we have now.By "code patterns", you mean something like this? struct Foo { int getBar(); void setBar(int); } void main() { Foo foo; int a =3D foo.bar; // calls getBar() foo.bar =3D a; // calls setBar(a) }
Dec 14 2011
On Wed, 14 Dec 2011 13:27:57 -0000, Regan Heath <regan netmail.co.nz> = wrote:On Wed, 14 Dec 2011 02:36:43 -0000, Michel Fortin =<michel.fortin michelf.com> wrote:On 2011-12-13 23:08:43 +0000, Andrei Alexandrescu =<SeeWebsiteForEmail erdani.org> said:We could have inferred property intention from the code pattern, =d =without requiring any keyword. That solution (which was discussed an=rejected in this newsgroup) was miles ahead from the drivel of =nd =struct Foo { int bar // <- does DMD do lookahead? detect { instead of ; here a=property we have now.By "code patterns", you mean something like this? struct Foo { int getBar(); void setBar(int); } void main() { Foo foo; int a =3D foo.bar; // calls getBar() foo.bar =3D a; // calls setBar(a) }trigger "property" parsing { get { return this; // <- 'this' meaning the 'bar' member } set { this =3D value; // <- 'this' meaning the 'bar' member, 'value' ==meaning the RHS of the "=A3instance.bar =3D <value>" statement } } } ReganApologies, there was a typo/mistake in the 'get' above. :) Regan -- = Using Opera's revolutionary email client: http://www.opera.com/mail/
Dec 14 2011
On 2011-12-14 13:27:57 +0000, "Regan Heath" <regan netmail.co.nz> said:On Wed, 14 Dec 2011 02:36:43 -0000, Michel Fortin <michel.fortin michelf.com> wrote:address of the getter with it? And how do you define array-member properties like you can do with functions? And how do you disambiguate access those array members properties if two imported modules define a property with the same name for an array? It basically has the same undefined areas as the current syntax using property. With the code pattern syntax used above: &foo.bar; // take the address of the returned value (if returned by ref) &foo.getBar; // take the address of the getter &foo.setBar; // take the address of the setter void getFront(int[] array) { return array[0]; } int[] a; a.front; // array-member property made from a module-level function // disambiguated access if two imported modules // define the same array-member property std.range.getFront(a); other.mod.getFront(a); -- Michel Fortin michel.fortin michelf.com http://michelf.com/By "code patterns", you mean something like this? struct Foo { int getBar(); void setBar(int); } void main() { Foo foo; int a = foo.bar; // calls getBar() foo.bar = a; // calls setBar(a) }
Dec 14 2011
On Wed, 14 Dec 2011 13:50:09 -0000, Michel Fortin <michel.fortin michelf.com> wrote:On 2011-12-14 13:27:57 +0000, "Regan Heath" <regan netmail.co.nz> said:I hadn't given this a lot of thought. But, here goes.. :) The compiler (whatever the syntax used) will generate the get/set functions internally. So, it will technically be possible to take the address of both the getter and setter. Using my suggested syntax there is only 1 property name 'bar' and typically the function called is determined by the usage, e.g. Foo foo; int a = foo.bar; // getter called foo.bar = 4; // setter called So, what happens when we take the address.. Foo foo; int delegate(void) getter = &foo.bar; // takes the address of the getter void delegate(in) setter = &foo.bar; // takes the address of the setter I think that works, what do you reckon?On Wed, 14 Dec 2011 02:36:43 -0000, Michel Fortin <michel.fortin michelf.com> wrote:address of the getter with it?By "code patterns", you mean something like this? struct Foo { int getBar(); void setBar(int); } void main() { Foo foo; int a = foo.bar; // calls getBar() foo.bar = a; // calls setBar(a) }And how do you define array-member properties like you can do with functions?I don't think we should call these "properties". What we're actually doing is adding members to built in types which can have any number of arguments and are therefore they're not strictly "properties". I think part of the confusion around properties comes from conflating these two ideas into one and calling them both "properties".And how do you disambiguate access those array members properties if two imported modules define a property with the same name for an array?I'd like to split the "adding array members" feature away from "properties" and look at it again, specifically due to problem cases like this. For example, in this case we could require the use of () for "adding array members" while for actual properties (user defined, on user to be used. I think that pretty much avoids the whole can of worms, doesn't it? Regan -- Using Opera's revolutionary email client: http://www.opera.com/mail/
Dec 14 2011
On Tue, 13 Dec 2011 18:08:43 -0500, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:On 12/13/11 5:14 PM, Peter Alexander wrote:property wasn't my first choice, there were probably a dozen proposals on http://prowiki.org/wiki4d/wiki.cgi?LanguageDevel/DIPs/DIP4 But here is the phenomenon I noticed: N different solutions get proposed, and are debated by the community. Walter is very vocal about what he doesn't like, but silent on other aspects (presumably because he is considering them?) All of a sudden Walter picks a solution, then posts a thread to flesh out the details. After that, it's hard to change his mind. For the property debate, looking back through the newsgroups, it looks like Walter and you came up with a solution that nobody had proposed and nobody liked. Then somehow property was chosen. Not sure how that happened or what the convincing argument was. But you will notice in that discussion that many of the solutions did not involve keywords, and all were given equal air time (I don't see tunnel vision). Thread: http://dfeed.kimsufi.thecybershadow.net/discussion/post/h53g3i$elk$1 digitalmars.com I personally don't mind property, even if there are better solutions. It's not as horrible as you say IMO. -SteveOn 13/12/11 10:17 PM, Vladimir Panteleev wrote:We could have inferred property intention from the code pattern, without requiring any keyword. That solution (which was discussed and rejected in this newsgroup) was miles ahead from the drivel of property we have now. I noticed there's a tunnel vision phenomenon when it comes to keyword-based solutions: once a special notation is on the table, there's no appreciation for anything else. That's what happened with lazy (another design misfire I'm very unhappy about) and with property. I literally feel my heart rate getting up when I think of them.On Tuesday, 13 December 2011 at 21:10:22 UTC, Andrei Alexandrescu wrote:In my opinion, it's not better than nothing. What it gives you: 1. A bit of syntactic sugar. 2. The ability to refactor member look up easily. What it costs: 1. Overloads syntax. a. obj.field can now be an arbitrary function call. b. May have arbitrary cost (e.g. T[].length) 2. Complicating the language (proof: this discussion) 3. Another thing to learn. 4. Another thing for tools to process. I don't think the syntax sugar it provides counts for anything really. The ability to refactor member look ups is nice, but I find that this rarely occurs in practice and even when it occurs, it's not hard to replace obj.field with obj.field() or obj.getField(). The costs far outweigh the benefits IMO.There's a phrase in Romanian that quite applies: "From the lake into the well".I believe the English version is "Out of the frying pan, into the fire" :) Inconsequential space-filler opinion: I am OK with property, mainly because it's a common feature among PLs, it's better than nothing, and don't know better solutions.
Dec 14 2011
I don't mind property, usually I just create one property block for a class, e.g.: property { // funcs.. }
Dec 14 2011
On 12/14/2011 12:14 AM, Peter Alexander wrote:On 13/12/11 10:17 PM, Vladimir Panteleev wrote:??? T[].length is a field access, not a property function. It takes a small constant amount of time.On Tuesday, 13 December 2011 at 21:10:22 UTC, Andrei Alexandrescu wrote:In my opinion, it's not better than nothing. What it gives you: 1. A bit of syntactic sugar. 2. The ability to refactor member look up easily. What it costs: 1. Overloads syntax. a. obj.field can now be an arbitrary function call. b. May have arbitrary cost (e.g. T[].length)There's a phrase in Romanian that quite applies: "From the lake into the well".I believe the English version is "Out of the frying pan, into the fire" :) Inconsequential space-filler opinion: I am OK with property, mainly because it's a common feature among PLs, it's better than nothing, and don't know better solutions.2. Complicating the language (proof: this discussion) 3. Another thing to learn. 4. Another thing for tools to process. I don't think the syntax sugar it provides counts for anything really. The ability to refactor member look ups is nice, but I find that this rarely occurs in practice and even when it occurs, it's not hard to replace obj.field with obj.field() or obj.getField(). The costs far outweigh the benefits IMO.
Dec 13 2011
On 13/12/11 11:11 PM, Timon Gehr wrote:On 12/14/2011 12:14 AM, Peter Alexander wrote:Assigning to the length of an array may reallocate it, which is not a small, nor constant amount of time. int[] a; ... a.length = n; // may invoke a GC allocation + O(n) memcpyOn 13/12/11 10:17 PM, Vladimir Panteleev wrote:??? T[].length is a field access, not a property function. It takes a small constant amount of time.On Tuesday, 13 December 2011 at 21:10:22 UTC, Andrei Alexandrescu wrote:In my opinion, it's not better than nothing. What it gives you: 1. A bit of syntactic sugar. 2. The ability to refactor member look up easily. What it costs: 1. Overloads syntax. a. obj.field can now be an arbitrary function call. b. May have arbitrary cost (e.g. T[].length)There's a phrase in Romanian that quite applies: "From the lake into the well".I believe the English version is "Out of the frying pan, into the fire" :) Inconsequential space-filler opinion: I am OK with property, mainly because it's a common feature among PLs, it's better than nothing, and don't know better solutions.
Dec 13 2011
On 12/14/2011 12:35 AM, Peter Alexander wrote:On 13/12/11 11:11 PM, Timon Gehr wrote:OK, I see, thanks. I don't think it is problematic in this particular case though.On 12/14/2011 12:14 AM, Peter Alexander wrote:Assigning to the length of an array may reallocate it, which is not a small, nor constant amount of time. int[] a; ... a.length = n; // may invoke a GC allocation + O(n) memcpyOn 13/12/11 10:17 PM, Vladimir Panteleev wrote:??? T[].length is a field access, not a property function. It takes a small constant amount of time.On Tuesday, 13 December 2011 at 21:10:22 UTC, Andrei Alexandrescu wrote:In my opinion, it's not better than nothing. What it gives you: 1. A bit of syntactic sugar. 2. The ability to refactor member look up easily. What it costs: 1. Overloads syntax. a. obj.field can now be an arbitrary function call. b. May have arbitrary cost (e.g. T[].length)There's a phrase in Romanian that quite applies: "From the lake into the well".I believe the English version is "Out of the frying pan, into the fire" :) Inconsequential space-filler opinion: I am OK with property, mainly because it's a common feature among PLs, it's better than nothing, and don't know better solutions.
Dec 14 2011
On 14/12/11 8:16 AM, Timon Gehr wrote:On 12/14/2011 12:35 AM, Peter Alexander wrote:Well, it is a little. It makes it difficult to scan code looking for GC allocations, or even scan code looking for inefficiencies. Obviously I know now that I have to look for .length assignments on arrays, but it can be quite horrific when looking at code that uses third party libraries that you aren't familiar with. An example of this I encountered in practice was in Unity3D's libraries. http://unity3d.com/support/documentation/ScriptReference/WWW-texture.html The WWW class has a 'texture' property. A small sentence in the middle of its documentation reveals the horror. "Each invocation of texture property allocates a new Texture2D." That's right. Every time you read WWW.texture, it allocates a large chunk of memory. In my particular case, I was copying the pixels from the texture into another array, something like this: WWW www = ...; for (int i = 0; i < www.texture.width; ++i) for (int j = 0; j < www.texture.height; ++j) buffer[i][j] = www.texture.GetPixel(i, j); For a small 100x100 texture, that code allocates over 10,000, 100x100 textures. Luckily, that was horrific enough to prompt me to investigate, but a less obvious problem would have likely slipped past me unnoticed.On 13/12/11 11:11 PM, Timon Gehr wrote:OK, I see, thanks. I don't think it is problematic in this particular case though.On 12/14/2011 12:14 AM, Peter Alexander wrote:Assigning to the length of an array may reallocate it, which is not a small, nor constant amount of time. int[] a; ... a.length = n; // may invoke a GC allocation + O(n) memcpyOn 13/12/11 10:17 PM, Vladimir Panteleev wrote:??? T[].length is a field access, not a property function. It takes a small constant amount of time.On Tuesday, 13 December 2011 at 21:10:22 UTC, Andrei Alexandrescu wrote:In my opinion, it's not better than nothing. What it gives you: 1. A bit of syntactic sugar. 2. The ability to refactor member look up easily. What it costs: 1. Overloads syntax. a. obj.field can now be an arbitrary function call. b. May have arbitrary cost (e.g. T[].length)There's a phrase in Romanian that quite applies: "From the lake into the well".I believe the English version is "Out of the frying pan, into the fire" :) Inconsequential space-filler opinion: I am OK with property, mainly because it's a common feature among PLs, it's better than nothing, and don't know better solutions.
Dec 14 2011
On 12/14/2011 09:39 PM, Peter Alexander wrote:On 14/12/11 8:16 AM, Timon Gehr wrote:Oh yes, certainly. That is what I meant by 'in this particular case': Because the .length on arrays is built into the language, you know that it must allocate as soon as you have a sufficiently good mental model of how dynamic arrays work. (and anyone who wants to write effective D code that uses dynamic arrays should)On 12/14/2011 12:35 AM, Peter Alexander wrote:Well, it is a little. It makes it difficult to scan code looking for GC allocations, or even scan code looking for inefficiencies. Obviously I know now that I have to look for .length assignments on arrays, but it can be quite horrific when looking at code that uses third party libraries that you aren't familiar with.On 13/12/11 11:11 PM, Timon Gehr wrote:OK, I see, thanks. I don't think it is problematic in this particular case though.On 12/14/2011 12:14 AM, Peter Alexander wrote:Assigning to the length of an array may reallocate it, which is not a small, nor constant amount of time. int[] a; ... a.length = n; // may invoke a GC allocation + O(n) memcpyOn 13/12/11 10:17 PM, Vladimir Panteleev wrote:??? T[].length is a field access, not a property function. It takes a small constant amount of time.On Tuesday, 13 December 2011 at 21:10:22 UTC, Andrei Alexandrescu wrote:In my opinion, it's not better than nothing. What it gives you: 1. A bit of syntactic sugar. 2. The ability to refactor member look up easily. What it costs: 1. Overloads syntax. a. obj.field can now be an arbitrary function call. b. May have arbitrary cost (e.g. T[].length)There's a phrase in Romanian that quite applies: "From the lake into the well".I believe the English version is "Out of the frying pan, into the fire" :) Inconsequential space-filler opinion: I am OK with property, mainly because it's a common feature among PLs, it's better than nothing, and don't know better solutions.An example of this I encountered in practice was in Unity3D's libraries. http://unity3d.com/support/documentation/ScriptReference/WWW-texture.html The WWW class has a 'texture' property. A small sentence in the middle of its documentation reveals the horror. "Each invocation of texture property allocates a new Texture2D." That's right. Every time you read WWW.texture, it allocates a large chunk of memory. In my particular case, I was copying the pixels from the texture into another array, something like this: WWW www = ...; for (int i = 0; i < www.texture.width; ++i) for (int j = 0; j < www.texture.height; ++j) buffer[i][j] = www.texture.GetPixel(i, j); For a small 100x100 texture, that code allocates over 10,000, 100x100 textures. Luckily, that was horrific enough to prompt me to investigate, but a less obvious problem would have likely slipped past me unnoticed.oO. That is quite an API design problem there.
Dec 14 2011
Peter Alexander:Well, it is a little. It makes it difficult to scan code looking for GC allocations, or even scan code looking for inefficiencies. Obviously I know now that I have to look for .length assignments on arrays, but it can be quite horrific when looking at code that uses third party libraries that you aren't familiar with.A proposed idea to help is to add a compilation switch that produces a list of all heap allocation points in the current compilation unit (in Bugzilla there is a related issue that asks for a list of just heap allocations of closures). Bye, bearophile
Dec 14 2011
On Wed, 14 Dec 2011 15:39:55 -0500, Peter Alexander <peter.alexander.au gmail.com> wrote:On 14/12/11 8:16 AM, Timon Gehr wrote:Yes, but length as a read property does not allocate anything (nor does reducing the length). In fact, length as a read property reduces to a field access (it is a language builtin, after all). Would you expect that setting the length of an array to a *larger* size would not allocate? Your example shows something that doesn't look like it should be costly, but it actually is. Expanding length *looks* costly (and it is). You do have a point that it shouldn't necessarily be a property. I also don't think dup, reverse, or sort should be array properties. But these are pieces of the language that have been there forever. To change them now would be disruptive for very little gain. -SteveOn 12/14/2011 12:35 AM, Peter Alexander wrote:Well, it is a little. It makes it difficult to scan code looking for GC allocations, or even scan code looking for inefficiencies. Obviously I know now that I have to look for .length assignments on arrays, but it can be quite horrific when looking at code that uses third party libraries that you aren't familiar with. An example of this I encountered in practice was in Unity3D's libraries. http://unity3d.com/support/documentation/ScriptReference/WWW-texture.html The WWW class has a 'texture' property. A small sentence in the middle of its documentation reveals the horror. "Each invocation of texture property allocates a new Texture2D." That's right. Every time you read WWW.texture, it allocates a large chunk of memory. In my particular case, I was copying the pixels from the texture into another array, something like this: WWW www = ...; for (int i = 0; i < www.texture.width; ++i) for (int j = 0; j < www.texture.height; ++j) buffer[i][j] = www.texture.GetPixel(i, j); For a small 100x100 texture, that code allocates over 10,000, 100x100 textures. Luckily, that was horrific enough to prompt me to investigate, but a less obvious problem would have likely slipped past me unnoticed.On 13/12/11 11:11 PM, Timon Gehr wrote:OK, I see, thanks. I don't think it is problematic in this particular case though.On 12/14/2011 12:14 AM, Peter Alexander wrote:Assigning to the length of an array may reallocate it, which is not a small, nor constant amount of time. int[] a; ... a.length = n; // may invoke a GC allocation + O(n) memcpyOn 13/12/11 10:17 PM, Vladimir Panteleev wrote:??? T[].length is a field access, not a property function. It takes a small constant amount of time.On Tuesday, 13 December 2011 at 21:10:22 UTC, Andrei Alexandrescu wrote:In my opinion, it's not better than nothing. What it gives you: 1. A bit of syntactic sugar. 2. The ability to refactor member look up easily. What it costs: 1. Overloads syntax. a. obj.field can now be an arbitrary function call. b. May have arbitrary cost (e.g. T[].length)There's a phrase in Romanian that quite applies: "From the lake into the well".I believe the English version is "Out of the frying pan, into the fire" :) Inconsequential space-filler opinion: I am OK with property, mainly because it's a common feature among PLs, it's better than nothing, and don't know better solutions.
Dec 14 2011
Steven Schveighoffer:I also don't think dup, reverse, or sort should be array properties. But these are pieces of the language that have been there forever. To change them now would be disruptive for very little gain.sort and reverse properties will be deprecated and later removed. Bye, bearophile
Dec 14 2011
On 14/12/11 8:59 PM, Steven Schveighoffer wrote:On Wed, 14 Dec 2011 15:39:55 -0500, Peter Alexander <peter.alexander.au gmail.com> wrote:Length reading is fine.On 14/12/11 8:16 AM, Timon Gehr wrote:Yes, but length as a read property does not allocate anything (nor does reducing the length). In fact, length as a read property reduces to a field access (it is a language builtin, after all).On 12/14/2011 12:35 AM, Peter Alexander wrote:Well, it is a little. It makes it difficult to scan code looking for GC allocations, or even scan code looking for inefficiencies. Obviously I know now that I have to look for .length assignments on arrays, but it can be quite horrific when looking at code that uses third party libraries that you aren't familiar with. An example of this I encountered in practice was in Unity3D's libraries. http://unity3d.com/support/documentation/ScriptReference/WWW-texture.html The WWW class has a 'texture' property. A small sentence in the middle of its documentation reveals the horror. "Each invocation of texture property allocates a new Texture2D." That's right. Every time you read WWW.texture, it allocates a large chunk of memory. In my particular case, I was copying the pixels from the texture into another array, something like this: WWW www = ...; for (int i = 0; i < www.texture.width; ++i) for (int j = 0; j < www.texture.height; ++j) buffer[i][j] = www.texture.GetPixel(i, j); For a small 100x100 texture, that code allocates over 10,000, 100x100 textures. Luckily, that was horrific enough to prompt me to investigate, but a less obvious problem would have likely slipped past me unnoticed.On 13/12/11 11:11 PM, Timon Gehr wrote:OK, I see, thanks. I don't think it is problematic in this particular case though.On 12/14/2011 12:14 AM, Peter Alexander wrote:Assigning to the length of an array may reallocate it, which is not a small, nor constant amount of time. int[] a; ... a.length = n; // may invoke a GC allocation + O(n) memcpyOn 13/12/11 10:17 PM, Vladimir Panteleev wrote:??? T[].length is a field access, not a property function. It takes a small constant amount of time.On Tuesday, 13 December 2011 at 21:10:22 UTC, Andrei Alexandrescu wrote:In my opinion, it's not better than nothing. What it gives you: 1. A bit of syntactic sugar. 2. The ability to refactor member look up easily. What it costs: 1. Overloads syntax. a. obj.field can now be an arbitrary function call. b. May have arbitrary cost (e.g. T[].length)There's a phrase in Romanian that quite applies: "From the lake into the well".I believe the English version is "Out of the frying pan, into the fire" :) Inconsequential space-filler opinion: I am OK with property, mainly because it's a common feature among PLs, it's better than nothing, and don't know better solutions.Would you expect that setting the length of an array to a *larger* size would not allocate? Your example shows something that doesn't look like it should be costly, but it actually is. Expanding length *looks* costly (and it is).It's not that I wouldn't expect it (I would), but at a glance (i.e. without thinking about it) you wouldn't notice it. It just looks like a member assignment. It's like overloading operator& in C++. It takes something that had one meaning and changes it into something else without a change in syntax. It's essentially the syntactic version of function hijacking.You do have a point that it shouldn't necessarily be a property. I also don't think dup, reverse, or sort should be array properties. But these are pieces of the language that have been there forever. To change them now would be disruptive for very little gain.Agreed.
Dec 14 2011
On 13.12.2011 23:17, Vladimir Panteleev wrote:On Tuesday, 13 December 2011 at 21:10:22 UTC, Andrei Alexandrescu wrote:The Norwegian version is "From ashes to fire" (direct translation) or "From the ashes into the fire"There's a phrase in Romanian that quite applies: "From the lake into the well".I believe the English version is "Out of the frying pan, into the fire" :)
Dec 14 2011
On Tuesday, December 13, 2011 12:25:12 Jonathan M Davis wrote:On Tuesday, December 13, 2011 14:02:51 Andrei Alexandrescu wrote:In fact, what _would_ you prefer to property if it's not what we had before? - Jonathan M DavisOn 12/13/11 10:32 AM, Jonathan M Davis wrote:I'm not saying that those are the only choices, but you seem to think that the current situation is worse than what we had before, which I don't understand. The current situation looks all around better to me.On Monday, December 12, 2011 18:00:35 Andrei Alexandrescu wrote:No. That would be a false choice.On 12/12/11 1:12 PM, Jonathan M Davis wrote:So, you prefer the situation where any function with no arguments can be used as a getter and any function with a single argument can be used as a setter?On Monday, December 12, 2011 08:46:18 Andrei Alexandrescu wrote:Other than it being completely useless, requiring more rote memorization, and fomenting time-wasting discussion? None.Insisting on the current property semantics was a sizeable mistake of this community, and I am sorry we gave into it.Aside from the fact that the behavior of -property isn't the default, what's the problem with property?
Dec 13 2011
On 12/12/11 6:24 AM, torhu wrote:save being a property is a stupid inconsistency.I'm not so sure. Andrei
Dec 12 2011
On 12.12.2011 15:43, Andrei Alexandrescu wrote:On 12/12/11 6:24 AM, torhu wrote:Why? As far as I can tell, it's inconsistent with what properties are used like in other programming languages. Saving something is an action, which to me is a different concept. If it was called currentState instead, that's what I'd call a property. Making something a property gives it certain connotations that break when it's called 'save'. That you can save the state of the range is a property, if you will. But the action of doing so is not a property. People are going to be surprised when save() doesn't compile. Isn't there something called the principle of least surprise?save being a property is a stupid inconsistency.I'm not so sure. Andrei
Dec 12 2011
On 12/12/11 9:09 AM, torhu wrote:On 12.12.2011 15:43, Andrei Alexandrescu wrote:Why?On 12/12/11 6:24 AM, torhu wrote:Why? As far as I can tell, it's inconsistent with what properties are used like in other programming languages.save being a property is a stupid inconsistency.I'm not so sure. AndreiSaving something is an action, which to me is a different concept.So if we called .save .state or .current things would be any different?If it was called currentState instead, that's what I'd call a property.Ah. So now we're wasting time not on property (as I'd predicted), but instead on what _names_ are suitable to work with it. I rest my case.Making something a property gives it certain connotations that break when it's called 'save'. That you can save the state of the range is a property, if you will. But the action of doing so is not a property. People are going to be surprised when save() doesn't compile. Isn't there something called the principle of least surprise?I think we should only worry about surprising the uninitiated with how poorly designed the whole property thing is. Andrei
Dec 12 2011
On 12.12.2011 16:16, Andrei Alexandrescu wrote:On 12/12/11 9:09 AM, torhu wrote:Yes, completely. The whole property concept is basically a naming convention. Except that parentheses are now involved. x = obj.foo(); // do the foo thing, then return something x = obj.bar; // get bar obj.bar = 42; // set bar x = obj.save; // get save... hm, that doesn't sound rightOn 12.12.2011 15:43, Andrei Alexandrescu wrote:Why?On 12/12/11 6:24 AM, torhu wrote:Why? As far as I can tell, it's inconsistent with what properties are used like in other programming languages.save being a property is a stupid inconsistency.I'm not so sure. AndreiSaving something is an action, which to me is a different concept.So if we called .save .state or .current things would be any different?I'm not trying to defend property, I think it adds about as much pain as it does gain. But it's there, and your ranges are using it :)If it was called currentState instead, that's what I'd call a property.Ah. So now we're wasting time not on property (as I'd predicted), but instead on what _names_ are suitable to work with it. I rest my case.Making something a property gives it certain connotations that break when it's called 'save'. That you can save the state of the range is a property, if you will. But the action of doing so is not a property. People are going to be surprised when save() doesn't compile. Isn't there something called the principle of least surprise?I think we should only worry about surprising the uninitiated with how poorly designed the whole property thing is.
Dec 12 2011
On 12/12/11 3:16 PM, Andrei Alexandrescu wrote:On 12/12/11 9:09 AM, torhu wrote:My understanding is the properties are essentially meant to be indistinguishable from fields (hence the syntax). save() doesn't really act like a field. Honestly though, I don't like properties at all (in any language). Function calls should not be hidden in syntax. IMO if your code contains so many get/set functions that properties save you time then you have bigger issues.On 12.12.2011 15:43, Andrei Alexandrescu wrote:Why?On 12/12/11 6:24 AM, torhu wrote:Why? As far as I can tell, it's inconsistent with what properties are used like in other programming languages.save being a property is a stupid inconsistency.I'm not so sure. Andrei
Dec 12 2011
On Monday, December 12, 2011 09:16:53 Andrei Alexandrescu wrote:On 12/12/11 9:09 AM, torhu wrote:A property is essentially an abstraction to treat a function like a member variable. As such, the naming conventions for a property should be equivalent to those for a variable - and that generally means nouns. save is not a noun. It's an action verb. So, yes, I think that it's a completely inappropriate name for a property. Something ilke state or current _would_ be appropriate names. However, at this point, I really don't think that it's worth arguing about. If I were to change it, I'd probably just make save a function rather than renaming it, but if we did it, then there would be quite a bit of code that would have to be changed essentially over an argument over whether save is valid property name because it's not a noun. And while I _don't_ think that it's a valid property name, that's getting a bit petty given how much code would break. I'm all for fixing names for camelcasing, because that really affects the consistency of the library and is almost always completely objective, but this is essentially an argument over the best name for a function, and that never has a clear answer. Yes, it's an issue of consistency on some level with regards to how we treat and name properties, but that's subjective enough that I don't expect us to ever be completely consistent on that. - Jonathan M DavisOn 12.12.2011 15:43, Andrei Alexandrescu wrote:Why?On 12/12/11 6:24 AM, torhu wrote:Why? As far as I can tell, it's inconsistent with what properties are used like in other programming languages.save being a property is a stupid inconsistency.I'm not so sure. AndreiSaving something is an action, which to me is a different concept.So if we called .save .state or .current things would be any different?If it was called currentState instead, that's what I'd call a property.Ah. So now we're wasting time not on property (as I'd predicted), but instead on what _names_ are suitable to work with it. I rest my case.Making something a property gives it certain connotations that break when it's called 'save'. That you can save the state of the range is a property, if you will. But the action of doing so is not a property. People are going to be surprised when save() doesn't compile. Isn't there something called the principle of least surprise?I think we should only worry about surprising the uninitiated with how poorly designed the whole property thing is.
Dec 12 2011
On 12.12.2011 20:03, Jonathan M Davis wrote:On Monday, December 12, 2011 09:16:53 Andrei Alexandrescu wrote:It's actually not 'save' being a noun that's the problem. I just thought of a counter-example: --- struct Foo { // the data Bar data[]; // save data on shutdown? property bool save() { return save_; } property bool save(bool shouldShave) { return save_ = shouldSave; } private: bool save_; } --- Not meant to be a realistic example, but save is fine as a property here.On 12/12/11 9:09 AM, torhu wrote: > On 12.12.2011 15:43, Andrei Alexandrescu wrote: >> On 12/12/11 6:24 AM, torhu wrote: >>> save being a property is a stupid inconsistency. >> >> I'm not so sure. >> >> Andrei > > Why? As far as I can tell, it's inconsistent with what properties are > used like in other programming languages. Why? > Saving something is an action, > which to me is a different concept. So if we called .save .state or .current things would be any different? > If it was called currentState > instead, that's what I'd call a property. Ah. So now we're wasting time not on property (as I'd predicted), but instead on what _names_ are suitable to work with it. I rest my case. > Making something a property gives it certain connotations that break > when it's called 'save'. That you can save the state of the range is a > property, if you will. But the action of doing so is not a property. > People are going to be surprised when save() doesn't compile. Isn't > there something called the principle of least surprise? I think we should only worry about surprising the uninitiated with how poorly designed the whole property thing is.A property is essentially an abstraction to treat a function like a member variable. As such, the naming conventions for a property should be equivalent to those for a variable - and that generally means nouns. save is not a noun. It's an action verb. So, yes, I think that it's a completely inappropriate name for a property. Something ilke state or current _would_ be appropriate names. However, at this point, I really don't think that it's worth arguing about. If I were to change it, I'd probably just make save a function rather than renaming it, but if we did it, then there would be quite a bit of code that would have to be changed essentially over an argument over whether save is valid property name because it's not a noun. And while I _don't_ think that it's a valid property name, that's getting a bit petty given how much code would break.
Dec 12 2011
On Tuesday, December 13, 2011 02:28:29 torhu wrote:It's actually not 'save' being a noun that's the problem. I just thought of a counter-example: --- struct Foo { // the data Bar data[]; // save data on shutdown? property bool save() { return save_; } property bool save(bool shouldShave) { return save_ = shouldSave; } private: bool save_; } --- Not meant to be a realistic example, but save is fine as a property here.You can pretty much always come up with another function with a completely different purpose wit the same name. Personally, the _only_ issue that I have with save is the fact that it's a property. The name save works well enough, and I can't think of anything that's better. - Jonathan M Davis
Dec 12 2011
On 13.12.2011 02:39, Jonathan M Davis wrote:On Tuesday, December 13, 2011 02:28:29 torhu wrote:Yes, that's my opinion too.It's actually not 'save' being a noun that's the problem. I just thought of a counter-example: --- struct Foo { // the data Bar data[]; // save data on shutdown? property bool save() { return save_; } property bool save(bool shouldShave) { return save_ = shouldSave; } private: bool save_; } --- Not meant to be a realistic example, but save is fine as a property here.You can pretty much always come up with another function with a completely different purpose wit the same name. Personally, the _only_ issue that I have with save is the fact that it's a property. The name save works well enough, and I can't think of anything that's better.
Dec 12 2011
On Sun, 11 Dec 2011 06:16:33 -0500, Mehrdad <wfunction hotmail.com> wrote:On 12/11/2011 2:56 AM, David Nadlinger wrote:The very definition of save is that it's only defined if it's fast. So for example, a file range should not define save, it's an input range, not a forward range. IMO, the whole concept of save is crap anyways. I won't get into it again, search the NG archives if you want my opinion. -SteveOn 12/11/11 10:04 AM, Mehrdad wrote:Whoa what?! I didn't know save() is a property. In that case I stand corrected. :-) Nevertheless, I think that makes no sense. :P If something isn't a "property" of something else, it shouldn't be marked as such. But there are more reasons than that... of the word property: http://msdn.microsoft.com/en-us/library/ms182181.aspx Specifically: "Properties should behave as if they are fields; if the method cannot, it should not be changed to a property. Methods are better than properties in the following situations: - Calling the method two times in succession creates different results. - The method performs a time-consuming operation. The method is perceivably slower than the time that is required to set or get the value of a field." Since both of these can be true for all but the most trivial kinds of ranges (e.g. file-system-related enumerators/ranges would very likely need to re-open a handle to a directory in order to traverse it, which is both relatively time-consuming AND returns a different result every time, and could even unexpectedly fail due to permission/connectivity issues), I don't think it makes sense for save() to be a property.On 12/11/2011 12:57 AM, Andrei Alexandrescu wrote:No, it's correct like that, save() is a property. Even though I recently updated Phobos to compile with -property enabled, I agree with Andrei here that in many cases there will be no perfect consensus whether a given member should be a property or not, thus potentially adding an extra source of complexity, or rather annoyance. DavidI think you should write: auto copy = this.save;Ah good point, I forgot about that. Idk then. (You forgot the parentheses though. :P)
Dec 12 2011
Andrei Alexandrescu:I'm not sure. How many times have you been in a place in life where you had a const range on your hands, that's not an array? I haven't.How many times I have used reduce or map on constant arrays in D2? Only few times, using a cast(). Now I am using them. Bye, bearophile
Dec 11 2011
On 12/11/11 2:48 AM, bearophile wrote:Andrei Alexandrescu:Emphasis added:I'm not sure. How many times have you been in a place in life where you had a const range on your hands, that's not an array? I haven't.How many times I have used reduce or map on constant arrays in D2? Only few times, using a cast(). Now I am using them. Bye, bearophileAndreiI'm not sure. How many times have you been in a place in life where you had a const range on your hands, _that's_not_an_array_? I haven't.
Dec 11 2011
On Sunday, December 11, 2011 02:05:08 Andrei Alexandrescu wrote:On 12/11/11 1:30 AM, Jonathan M Davis wrote:I tend to avoid const ranges precisely because they pretty much never work. I'd use them more if a tail-const version of them were easily obtainable - _especially_ if they worked the same way that arrays are going to be working with IFTI. Also, as std.container is filled out, the number of ranges which aren't arrays will definitely increase. Right now, they're almost always arrays or arrays wrapped by other ranges, and often you have to call array on the wrapped ones anyway, so a large portion of the time at this point, ranges are arrays. And while that will still hold to some extent, that should lessen as std.container is fleshed out. And that means that issues with const ranges will increase. Also, it's completely inconsistent that you can pass a const array to a range- based function and have it work but not a const user-defined range. It may be that we could get the compiler to figure it out based on slicing (assuming that opSlice returns the same type as the range itself aside from constness - otherwise passing containers to range-based functions would instantiate on the containers, which would cause issues, especially since it would be the container being passed, not a slice). And if we could do that, then I don't think that there would be any need for opPassByValue, but without a solution along those lines, we're going to have people complaining about not being able to pass const value-type ranges to range-based functions. And as fantastic as template constraints are, they don't make it immediately obvious why the type failed - certainly nothing as nice as "Error: find does not work with a const range." I do think that there is merit in seeing whether we can get the compiler to use opSlice to do what opPassByValue would do, but I also think that we should do something about this issue, or const ranges will forever be a problem. The only reasons that I don't run into the issue more is because I avoid const with ranges and with such a sparse std.container, so many ranges are arrays. - Jonathan M DavisOn Sunday, December 11, 2011 01:16:28 Andrei Alexandrescu wrote:I'm not sure. How many times have you been in a place in life where you had a const range on your hands, that's not an array? I haven't.To truly confer user-defined types the same capability, we should define opPassByValue() which is implicitly invoked whenever an object is passed by value into a function. By default that is a do-nothing operator; for arrays it would do the cast thing (or, equivalently, invoke "[]" on the array), and people could define it to do whatever. We could do all that. The question is, is the added complexity justified?I think that it's completely justified. We need a way to define tail-constness for ranges. Given const's transitiveness, it's very easy to end up in a situation where you have a const range, and having a means to get a tail-const version of that range would be very valuable. I don't know if opPassByValue is the best solution, but if not, we at least need a similar one.
Dec 13 2011
Jonathan M Davis:I tend to avoid const ranges precisely because they pretty much never work. I'd use them more if a tail-const version of them were easily obtainable -This is what I was trying to answer to Andrei :-) Bye, bearophile
Dec 14 2011
On 2011-12-11 07:16:28 +0000, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> said:On 12/10/11 5:20 PM, Michel Fortin wrote:Sadly, I'm not using D in my daily work these days. It's mostly C++ and Objective-C. I'd like to replace those two with D using my DMD/Objective-C fork, but it's still incomplete (lacks memory management), and DMD having no 64-bit support on OSX was a showstopper -- in fact, it still is for DMD/Objective-C which still lacks support for Apple's modern Objective-C runtime used on the 64-bit side. And my inability to make D for Xcode work with Xcode 4 is hampering the effort too. When I start a new project I'll definitely try using D for it, but right now my D escapade is on hold. :-( -- Michel Fortin michel.fortin michelf.com http://michelf.com/Also seems strange to me that class references aren't included in that list, but then I though about how tail-const still doesn't work with objects. You'd need my const(Object)ref patch to make that work, and Walter hasn't taken time to look at it yet…Have you continued to use your fork in daily work? If so, how does it pan out?
Dec 11 2011
On 2011-12-11 13:46, Michel Fortin wrote:On 2011-12-11 07:16:28 +0000, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> said:It seems 64bit support will be available in the upcoming release (DMD for D1 has already been released). -- /Jacob CarlborgOn 12/10/11 5:20 PM, Michel Fortin wrote:Sadly, I'm not using D in my daily work these days. It's mostly C++ and Objective-C. I'd like to replace those two with D using my DMD/Objective-C fork, but it's still incomplete (lacks memory management), and DMD having no 64-bit support on OSX was a showstopper -- in fact, it still is for DMD/Objective-C which still lacks support for Apple's modern Objective-C runtime used on the 64-bit side. And my inability to make D for Xcode work with Xcode 4 is hampering the effort too.Also seems strange to me that class references aren't included in that list, but then I though about how tail-const still doesn't work with objects. You'd need my const(Object)ref patch to make that work, and Walter hasn't taken time to look at it yet…Have you continued to use your fork in daily work? If so, how does it pan out?
Dec 12 2011
On 12/10/2011 4:47 PM, Andrei Alexandrescu wrote:We decided to fix this issue by automatically shedding the top-level const when passing an array or a pointer by value into a function.Really silly question: Why not do the same for primitives (int, float, char, etc.) or even structs without indirection? I've seen plenty of code that blows up when passed an immutable double because it tries to mutate its arguments. About 1.5 years ago I fixed a bug like this in std.math.pow().
Dec 11 2011
On 12/11/11 9:46 AM, dsimcha wrote:On 12/10/2011 4:47 PM, Andrei Alexandrescu wrote:Yes, that would be good to do as well. AndreiWe decided to fix this issue by automatically shedding the top-level const when passing an array or a pointer by value into a function.Really silly question: Why not do the same for primitives (int, float, char, etc.) or even structs without indirection? I've seen plenty of code that blows up when passed an immutable double because it tries to mutate its arguments. About 1.5 years ago I fixed a bug like this in std.math.pow().
Dec 11 2011
Le 11/12/2011 17:34, Andrei Alexandrescu a écrit :On 12/11/11 9:46 AM, dsimcha wrote:I was thinking about sugesting this. So obviously, this is a +1 to me.On 12/10/2011 4:47 PM, Andrei Alexandrescu wrote:Yes, that would be good to do as well. AndreiWe decided to fix this issue by automatically shedding the top-level const when passing an array or a pointer by value into a function.Really silly question: Why not do the same for primitives (int, float, char, etc.) or even structs without indirection? I've seen plenty of code that blows up when passed an immutable double because it tries to mutate its arguments. About 1.5 years ago I fixed a bug like this in std.math.pow().
Dec 11 2011
On 12/11/2011 05:34 PM, Andrei Alexandrescu wrote:On 12/11/11 9:46 AM, dsimcha wrote:+1. This also reduces template bloat, because IFTI wont create different instantiations when passed T, immutable(T), const(T).On 12/10/2011 4:47 PM, Andrei Alexandrescu wrote:Yes, that would be good to do as well. AndreiWe decided to fix this issue by automatically shedding the top-level const when passing an array or a pointer by value into a function.Really silly question: Why not do the same for primitives (int, float, char, etc.) or even structs without indirection? I've seen plenty of code that blows up when passed an immutable double because it tries to mutate its arguments. About 1.5 years ago I fixed a bug like this in std.math.pow().
Dec 11 2011
On Sunday, December 11, 2011 10:34:40 Andrei Alexandrescu wrote:On 12/11/11 9:46 AM, dsimcha wrote:Actually, that could be a problem for some stuff. It might be an acceptable problem, but it creates a problem nonetheless. What about containers? You can have arrays with immutable elements, but if you made it so that immutable int and int were the same as far as templates were concerned, then it would be impossible to have a container which held immutable elements. How big of a problem that is, I don't know, but I'd be concerned about some of the side effects. Another concern would be what would happen with primitives when they're inside of arrays. e.g. void func(T)(T[] arr) Having T lose its constness would be a big problem here. Now, if we're talking only IFTI - such func(cast(immutable int)2) instantiates with int and func!(immutable int)(2) still instantiates with immutable int - and it's only for primitives by themselves (e.g. func above is unaffected), then it likely isn't a problem. But we need to really look at the side effects of trying to treat primitives as mutable in templates. And if you're going to do that with primitives, it also opens up the question as to what to do with structs which are value types. Should they be treated the same? In theory, I think that stripping const and immutable from primitives at the top level could be a nice thing to have, but I'd be very concerned about how that would be implemented and what it would affect. We risk losing valuable type information and breaking existing code if it's not done right. - Jonathan M DavisOn 12/10/2011 4:47 PM, Andrei Alexandrescu wrote:Yes, that would be good to do as well.We decided to fix this issue by automatically shedding the top-level const when passing an array or a pointer by value into a function.Really silly question: Why not do the same for primitives (int, float, char, etc.) or even structs without indirection? I've seen plenty of code that blows up when passed an immutable double because it tries to mutate its arguments. About 1.5 years ago I fixed a bug like this in std.math.pow().
Dec 11 2011
On 12/11/2011 10:34 PM, Jonathan M Davis wrote:On Sunday, December 11, 2011 10:34:40 Andrei Alexandrescu wrote:Those issues are inexistent. int and immutable(int) are implicitly convertible to each other.On 12/11/11 9:46 AM, dsimcha wrote:Actually, that could be a problem for some stuff. It might be an acceptable problem, but it creates a problem nonetheless. What about containers? You can have arrays with immutable elements, but if you made it so that immutable int and int were the same as far as templates were concerned, then it would be impossible to have a container which held immutable elements. How big of a problem that is, I don't know, but I'd be concerned about some of the side effects.On 12/10/2011 4:47 PM, Andrei Alexandrescu wrote:Yes, that would be good to do as well.We decided to fix this issue by automatically shedding the top-level const when passing an array or a pointer by value into a function.Really silly question: Why not do the same for primitives (int, float, char, etc.) or even structs without indirection? I've seen plenty of code that blows up when passed an immutable double because it tries to mutate its arguments. About 1.5 years ago I fixed a bug like this in std.math.pow().Another concern would be what would happen with primitives when they're inside of arrays. e.g. void func(T)(T[] arr) Having T lose its constness would be a big problem here.Nobody suggested to do that.
Dec 11 2011
On Sunday, December 11, 2011 23:13:39 Timon Gehr wrote:On 12/11/2011 10:34 PM, Jonathan M Davis wrote:They may be implicitly convertible, but if you just outright stripped const and immutable from primitives, it would become impossible to instantiate a container which held const or immutable elements which were primitive.On Sunday, December 11, 2011 10:34:40 Andrei Alexandrescu wrote:Those issues are inexistent. int and immutable(int) are implicitly convertible to each other.On 12/11/11 9:46 AM, dsimcha wrote:Actually, that could be a problem for some stuff. It might be an acceptable problem, but it creates a problem nonetheless. What about containers? You can have arrays with immutable elements, but if you made it so that immutable int and int were the same as far as templates were concerned, then it would be impossible to have a container which held immutable elements. How big of a problem that is, I don't know, but I'd be concerned about some of the side effects.On 12/10/2011 4:47 PM, Andrei Alexandrescu wrote:Yes, that would be good to do as well.We decided to fix this issue by automatically shedding the top-level const when passing an array or a pointer by value into a function.Really silly question: Why not do the same for primitives (int, float, char, etc.) or even structs without indirection? I've seen plenty of code that blows up when passed an immutable double because it tries to mutate its arguments. About 1.5 years ago I fixed a bug like this in std.math.pow().That may be, but depending on how the removal of const on primitives were applied, it would happen. We need to make sure that it _doesn't_ happen. My point was not that this is a horrible idea but rather that we need to make sure that it targets what it's supposed to target and does not have side effects that reduce D's current capabilities. - Jonathan M DavisAnother concern would be what would happen with primitives when they're inside of arrays. e.g. void func(T)(T[] arr) Having T lose its constness would be a big problem here.Nobody suggested to do that.
Dec 11 2011
On 12/11/2011 11:19 PM, Jonathan M Davis wrote:On Sunday, December 11, 2011 23:13:39 Timon Gehr wrote:MyContainer!(immutable(int)).On 12/11/2011 10:34 PM, Jonathan M Davis wrote:They may be implicitly convertible, but if you just outright stripped const and immutable from primitives, it would become impossible to instantiate a container which held const or immutable elements which were primitive.On Sunday, December 11, 2011 10:34:40 Andrei Alexandrescu wrote:Those issues are inexistent. int and immutable(int) are implicitly convertible to each other.On 12/11/11 9:46 AM, dsimcha wrote:Actually, that could be a problem for some stuff. It might be an acceptable problem, but it creates a problem nonetheless. What about containers? You can have arrays with immutable elements, but if you made it so that immutable int and int were the same as far as templates were concerned, then it would be impossible to have a container which held immutable elements. How big of a problem that is, I don't know, but I'd be concerned about some of the side effects.On 12/10/2011 4:47 PM, Andrei Alexandrescu wrote:Yes, that would be good to do as well.We decided to fix this issue by automatically shedding the top-level const when passing an array or a pointer by value into a function.Really silly question: Why not do the same for primitives (int, float, char, etc.) or even structs without indirection? I've seen plenty of code that blows up when passed an immutable double because it tries to mutate its arguments. About 1.5 years ago I fixed a bug like this in std.math.pow().The qualifiers are stripped from the actual arguments, not from the template arguments.That may be, but depending on how the removal of const on primitives were applied, it would happen. We need to make sure that it _doesn't_ happen. My point was not that this is a horrible idea but rather that we need to make sure that it targets what it's supposed to target and does not have side effects that reduce D's current capabilities. - Jonathan M DavisAnother concern would be what would happen with primitives when they're inside of arrays. e.g. void func(T)(T[] arr) Having T lose its constness would be a big problem here.Nobody suggested to do that.
Dec 11 2011
On 12/11/11 4:19 PM, Jonathan M Davis wrote:On Sunday, December 11, 2011 23:13:39 Timon Gehr wrote:Timon is right, there's no issue. Top-level qualifier would be stripped ONLY when passing by-value into a function. AndreiOn 12/11/2011 10:34 PM, Jonathan M Davis wrote:They may be implicitly convertible, but if you just outright stripped const and immutable from primitives, it would become impossible to instantiate a container which held const or immutable elements which were primitive.On Sunday, December 11, 2011 10:34:40 Andrei Alexandrescu wrote:Those issues are inexistent. int and immutable(int) are implicitly convertible to each other.On 12/11/11 9:46 AM, dsimcha wrote:Actually, that could be a problem for some stuff. It might be an acceptable problem, but it creates a problem nonetheless. What about containers? You can have arrays with immutable elements, but if you made it so that immutable int and int were the same as far as templates were concerned, then it would be impossible to have a container which held immutable elements. How big of a problem that is, I don't know, but I'd be concerned about some of the side effects.On 12/10/2011 4:47 PM, Andrei Alexandrescu wrote:Yes, that would be good to do as well.We decided to fix this issue by automatically shedding the top-level const when passing an array or a pointer by value into a function.Really silly question: Why not do the same for primitives (int, float, char, etc.) or even structs without indirection? I've seen plenty of code that blows up when passed an immutable double because it tries to mutate its arguments. About 1.5 years ago I fixed a bug like this in std.math.pow().
Dec 11 2011
Le 11/12/2011 22:34, Jonathan M Davis a écrit :On Sunday, December 11, 2011 10:34:40 Andrei Alexandrescu wrote:I think you misunderstood the idea. The point was to remove constness of something passed by value, as long as it possible (native types, pointer (but not pointee), slices (but not what is in the slice), structs as long as they have no indirection in them). Has thoses are passed by value, the templated code will manipulate a copy of the data. So the original data can be immutable and the copied data can be mutable. This is not a big deal as theses data are differents ones.On 12/11/11 9:46 AM, dsimcha wrote:Actually, that could be a problem for some stuff. It might be an acceptable problem, but it creates a problem nonetheless. What about containers? You can have arrays with immutable elements, but if you made it so that immutable int and int were the same as far as templates were concerned, then it would be impossible to have a container which held immutable elements. How big of a problem that is, I don't know, but I'd be concerned about some of the side effects. Another concern would be what would happen with primitives when they're inside of arrays. e.g. void func(T)(T[] arr) Having T lose its constness would be a big problem here. Now, if we're talking only IFTI - such func(cast(immutable int)2) instantiates with int and func!(immutable int)(2) still instantiates with immutable int - and it's only for primitives by themselves (e.g. func above is unaffected), then it likely isn't a problem. But we need to really look at the side effects of trying to treat primitives as mutable in templates. And if you're going to do that with primitives, it also opens up the question as to what to do with structs which are value types. Should they be treated the same? In theory, I think that stripping const and immutable from primitives at the top level could be a nice thing to have, but I'd be very concerned about how that would be implemented and what it would affect. We risk losing valuable type information and breaking existing code if it's not done right. - Jonathan M DavisOn 12/10/2011 4:47 PM, Andrei Alexandrescu wrote:Yes, that would be good to do as well.We decided to fix this issue by automatically shedding the top-level const when passing an array or a pointer by value into a function.Really silly question: Why not do the same for primitives (int, float, char, etc.) or even structs without indirection? I've seen plenty of code that blows up when passed an immutable double because it tries to mutate its arguments. About 1.5 years ago I fixed a bug like this in std.math.pow().
Dec 11 2011
On 12/12/2011 12:33 AM, deadalnix wrote:I think you misunderstood the idea. The point was to remove constness of something passed by value, as long as it possible (native types, pointer (but not pointee), slices (but not what is in the slice), structs as long as they have no indirection in them).Then, should the rule be generalized to include any type that has no indirections to mutable data? struct S2 { immutable(int)* x; } struct S { string s; S2 s2; } void foo(T)(T s) if (!is(T == immutable)) { } immutable S s; foo(s); The argument is passed by value, the qualifier can be safely removed, so the call is rewritten to foo(cast(S)s); Any potential problems with that?
Dec 12 2011
On Sun, 11 Dec 2011 16:34:34 -0500, Jonathan M Davis <jmdavisProg gmx.com> wrote:On Sunday, December 11, 2011 10:34:40 Andrei Alexandrescu wrote:T does not lose its constness here. const(U[]) would go to const(U)[], which would then set T = const(U).On 12/11/11 9:46 AM, dsimcha wrote:Actually, that could be a problem for some stuff. It might be an acceptable problem, but it creates a problem nonetheless. What about containers? You can have arrays with immutable elements, but if you made it so that immutable int and int were the same as far as templates were concerned, then it would be impossible to have a container which held immutable elements. How big of a problem that is, I don't know, but I'd be concerned about some of the side effects. Another concern would be what would happen with primitives when they're inside of arrays. e.g. void func(T)(T[] arr) Having T lose its constness would be a big problem here.On 12/10/2011 4:47 PM, Andrei Alexandrescu wrote:Yes, that would be good to do as well.We decided to fix this issue by automatically shedding the top-level const when passing an array or a pointer by value into a function.Really silly question: Why not do the same for primitives (int, float, char, etc.) or even structs without indirection? I've seen plenty of code that blows up when passed an immutable double because it tries to mutate its arguments. About 1.5 years ago I fixed a bug like this in std.math.pow().Now, if we're talking only IFTI - such func(cast(immutable int)2) instantiates with int and func!(immutable int)(2) still instantiates with immutable int - and it's only for primitives by themselves (e.g. func above is unaffected), then it likely isn't a problem. But we need to really look at the side effects of trying to treat primitives as mutable in templates.We are talking only IFTI. Specifically, we are saying, for purposes of implying template parameters during IFTI, strip all the qualifiers from the pieces passed by value, as long as it doesn't affect any pieces passed by reference. I bet doing this one thing would instantly trim at least 10k of bloat from an executable. I'm looking at you, writeln.And if you're going to do that with primitives, it also opens up the question as to what to do with structs which are value types. Should they be treated the same?Yes. -Steve
Dec 12 2011