www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Re: const

reply Jason House <jason.james.house gmail.com> writes:
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
parent reply Walter Bright <newshound1 digitalmars.com> writes:
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
next sibling parent reply "Scott S. McCoy" <tag cpan.org> writes:
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
parent Walter Bright <newshound1 digitalmars.com> writes:
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
prev sibling next sibling parent reply Jason House <jason.james.house gmail.com> writes:
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
parent reply Walter Bright <newshound1 digitalmars.com> writes:
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
parent Michel Fortin <michel.fortin michelf.com> writes:
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
prev sibling parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
"Walter Bright" wrote
 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) { ... }

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
next sibling parent Bill Baxter <dnewsgroup billbaxter.com> writes:
Steven Schveighoffer wrote:
 "Walter Bright" wrote
 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) { ... }

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
prev sibling parent Michel Fortin <michel.fortin michelf.com> writes:
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