digitalmars.D - Re: const
- Jason House <jason.james.house gmail.com> Mar 28 2008
- Walter Bright <newshound1 digitalmars.com> Mar 28 2008
- "Scott S. McCoy" <tag cpan.org> Mar 28 2008
- Walter Bright <newshound1 digitalmars.com> Mar 28 2008
- Jason House <jason.james.house gmail.com> Mar 28 2008
- Walter Bright <newshound1 digitalmars.com> Mar 28 2008
- Michel Fortin <michel.fortin michelf.com> Mar 30 2008
- "Steven Schveighoffer" <schveiguy yahoo.com> Mar 31 2008
- Bill Baxter <dnewsgroup billbaxter.com> Mar 31 2008
- Michel Fortin <michel.fortin michelf.com> Mar 31 2008
Walter Bright Wrote:Jason House wrote:In my dream world implementation of all things const, D would do the following things: readonly (ro, or some variant) would mean a read only view invariant would mean the data never changes, period manifest declares a manifest constant const would have two meanings: 1. Variable declarations - a true constant 2. Function parameters - a promise not to modify the data
That's 5 different kinds of constants (as opposed to the current 3). I can hear the protests already <g>.
I'd hope that I only added one new kind of const. If I added more than that, then I screwed up :) Let me explain what I'm thinking. If we ignore the whole manifest constant thing, there's two kinds of constness right now. This leads to people defining const and invariant versions of functions, and defining functions with const and invariant versions of function arguments. Not really knowing how stuff will be used, or what kind of data will be present, they almost have to start mixing and matching, or just declare a few const variations and ignore the rest. Just imagine a function with 4 parameters that won't get modified. Should the coder provide 2^4=16 permutations of the same function? What's novel about what I was posting is that I want a way to have polysemous constness... A promise by the code writer to not modify the data, but saying *nothing* about what happens to the data outside of it's control. It's different than the current const type where you won't assume the data is invariant. Instead, it's saying that both const and invariant data is ok as an input and leaves it to be the compiler's job to do the right thing. I may be adding a new type of const, but it's a lazier form that I believe many D users would prefer to use. I'd expect this new type of polysemous const to be used very widely and push explicit declaration of an exact const format away from the every day user. In effect, I'm increasing the const types the *compiler* has to worry about but reducing what an average D user has to worry about to one const type!
Mar 28 2008
Jason House wrote:What's novel about what I was posting is that I want a way to have polysemous constness... A promise by the code writer to not modify the data, but saying *nothing* about what happens to the data outside of it's control. It's different than the current const type where you won't assume the data is invariant. Instead, it's saying that both const and invariant data is ok as an input and leaves it to be the compiler's job to do the right thing. I may be adding a new type of const, but it's a lazier form that I believe many D users would prefer to use. I'd expect this new type of polysemous const to be used very widely and push explicit declaration of an exact const format away from the every day user. In effect, I'm increasing the const types the *compiler* has to worry about but reducing what an average D user has to worry about to one const type!
I understand what you're saying. It's simply finding a method of transferring the 'constness' of the function argument to the function return type, without changing the contents of the function. Note that this is *not* a problem with const or invariant, it's a notational problem. This is currently done in C++ (and D) by writing each function twice. Obviously, that is hardly ideal. There have been some proposals to deal with it, but the current front runner is one Andrei came up with: typeof(a) foo(const(T) a) { ... } I'm worried it may have covariant/contravariant problems, but perhaps we can work that out.
Mar 28 2008
Content-Type: text/plain Content-Transfer-Encoding: 7bit The type inference provided by typeof(a) I think should be unnecessary. In fact, it's on the fringe of incoherency and it's meaning is a lot less than obvious. I have to ask, what's the difference between a const view into an immutable value, and a const view into an invariant value? Nothing right...so since you can't modify data from a const view of the data, and an invariant is a thing that can't be modified, shouldn't you be able to seamlessly promote an invariant to const, with no side effects? Cheers, Scott S. McCoy On Fri, 2008-03-28 at 18:31 -0700, Walter Bright wrote:typeof(a) foo(const(T) a) { ... }
Mar 28 2008
Scott S. McCoy wrote:I have to ask, what's the difference between a const view into an immutable value, and a const view into an invariant value? Nothing right...so since you can't modify data from a const view of the data, and an invariant is a thing that can't be modified, shouldn't you be able to seamlessly promote an invariant to const, with no side effects?
Yes, invariants can be implicitly converted to const.
Mar 28 2008
Walter Bright wrote:Jason House wrote:What's novel about what I was posting is that I want a way to have polysemous constness... A promise by the code writer to not modify the data, but saying *nothing* about what happens to the data outside of it's control. It's different than the current const type where you won't assume the data is invariant. Instead, it's saying that both const and invariant data is ok as an input and leaves it to be the compiler's job to do the right thing. I may be adding a new type of const, but it's a lazier form that I believe many D users would prefer to use. I'd expect this new type of polysemous const to be used very widely and push explicit declaration of an exact const format away from the every day user. In effect, I'm increasing the const types the *compiler* has to worry about but reducing what an average D user has to worry about to one const type!
I understand what you're saying. It's simply finding a method of transferring the 'constness' of the function argument to the function return type, without changing the contents of the function.
Ummm... no, I don't think you do. I guess I have a secret fear that except for exceptionally rare cases, invariant data will be pushed to the fringe of D. The problem is that it's very hard to declare any data as invariant, and there's no implicit casts to invariant. Excluding strings, it seems like 99% of normal usage will involve normal or const data. In most cases, const occurs through an implicit cast. For functions that won't change multiple arguments, the developer must choose how to declare each argument. For each, should it be const or invariant? Invariant will likely require an explicit (unsafe?) cast by the caller. Const denies the compiler some kind of optimization choice, but allows the caller to use the function freely. As a natural consequence of, functions will be written to accept const data for each argument. Extending this further, nearly all D code will be unable to take advantage of the compiler optimizations... And fall short of the grand hopes for D, missing the window of opportunity that multi-core provides.Note that this is *not* a problem with const or invariant, it's a notational problem. This is currently done in C++ (and D) by writing each function twice. Obviously, that is hardly ideal. There have been some proposals to deal with it, but the current front runner is one Andrei came up with: typeof(a) foo(const(T) a) { ... }
That's a very specific problem that I know has been under your radar, and I assume with time it'll get solved in a nice and clean way.I'm worried it may have covariant/contravariant problems, but perhaps we can work that out.
I don't know what you mean by that.
Mar 28 2008
Jason House wrote:Ummm... no, I don't think you do. I guess I have a secret fear that except for exceptionally rare cases, invariant data will be pushed to the fringe of D. The problem is that it's very hard to declare any data as invariant, and there's no implicit casts to invariant. Excluding strings, it seems like 99% of normal usage will involve normal or const data. In most cases, const occurs through an implicit cast.
I originally thought that would be true for strings, too, but it turns out that invariant strings are the overwhelming bulk of string usage. For most data structures, do they change once they're allocated and initialized? I don't know the answer to that, but I think we'll find out.Extending this further, nearly all D code will be unable to take advantage of the compiler optimizations... And fall short of the grand hopes for D, missing the window of opportunity that multi-core provides.
Or that using invariants will involve a shift in the style of programming, and the advantages of invariants will provide the push to change the style (like it did for strings).typeof(a) foo(const(T) a) { ... }
That's a very specific problem that I know has been under your radar, and I assume with time it'll get solved in a nice and clean way.I'm worried it may have covariant/contravariant problems, but perhaps we can work that out.
I don't know what you mean by that.
Imagine T is a base class, and a is a derived class. What is the typeof(a) ?
Mar 28 2008
On 2008-03-29 02:45:29 -0400, Walter Bright <newshound1 digitalmars.com> said:typeof(a) foo(const(T) a) { ... }
That's a very specific problem that I know has been under your radar, and I assume with time it'll get solved in a nice and clean way.I'm worried it may have covariant/contravariant problems, but perhaps we can work that out.
I don't know what you mean by that.
Imagine T is a base class, and a is a derived class. What is the typeof(a) ?
Good question indeed. I'd say the base class with the constness of the caller, but that's pretty ackward. I think the best solution would be to add generics to the language, so you can write your function like a template but it would only generate the code once: Derived foo(generic Derived : const(T))(Derived a) { ... } Obviously, generics would impose more limitations to what you can do than than regular templates. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Mar 30 2008
"Walter Bright" wroteI understand what you're saying. It's simply finding a method of transferring the 'constness' of the function argument to the function return type, without changing the contents of the function. Note that this is *not* a problem with const or invariant, it's a notational problem. This is currently done in C++ (and D) by writing each function twice. Obviously, that is hardly ideal. There have been some proposals to deal with it, but the current front runner is one Andrei came up with: typeof(a) foo(const(T) a) { ... }
What if the return can come from multiple inputs? Such as the min/max function: typeof(a or b?) min(const(T) a, const(T) b) {...} Note that if 'min' is called with a being mutable and b being invariant, the result must be const. What about declaring intermediate variables: typeof(a) foo(const(T) a) { ???(T) b = a; } How is this enforced? typeof(a) foo(const(T) a, const(T) b) { return b; } void f() { T a; invariant(T) b; a = foo(a, b); /// removes invariance of b, should be an error } I think in order to implement this properly, you need a new constancy modifier as we have discussed in 'const debacle' and 'proposal for scoped const contracts' Otherwise, you are relying on templates which would not always enforce the const contract, and which generate 3 identical functions. -Steve
Mar 31 2008
Steven Schveighoffer wrote:"Walter Bright" wroteI understand what you're saying. It's simply finding a method of transferring the 'constness' of the function argument to the function return type, without changing the contents of the function. Note that this is *not* a problem with const or invariant, it's a notational problem. This is currently done in C++ (and D) by writing each function twice. Obviously, that is hardly ideal. There have been some proposals to deal with it, but the current front runner is one Andrei came up with: typeof(a) foo(const(T) a) { ... }
What if the return can come from multiple inputs? Such as the min/max function: typeof(a or b?) min(const(T) a, const(T) b) {...}
And also what about the case of returning a member of a struct? typeof(Bar?) getBar(const(Foo) f) { return f.bar; } My problem with these new declarations is just that there are so many dang parentheses in the function signatures that it's hard to see what's what any more. --bb
Mar 31 2008
On 2008-03-31 11:45:09 -0400, "Steven Schveighoffer" <schveiguy yahoo.com> said:What about declaring intermediate variables: typeof(a) foo(const(T) a) { ???(T) b = a; } How is this enforced?
Well, can't you do that with a template? I don't have D 2 at hand right now, but shouldn't something like this do? T2 foo(T2 : const(T))(T2 a) { T2 b = a; } -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Mar 31 2008