December 06, 2007 Re: const again | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter Bright | On Thu, 06 Dec 2007 13:33:46 -0800, Walter Bright wrote: > As a result of all the const comments here, and some serious semantic problems discovered (dang it's hard to think of everything in advance), it seems there needs to be another tweak of the const behavior. I'm glad you're flexible ;-) > So, we're going to try a new, simpler regime: > const T x; > is semantically identical to: > const(T) x; > and the type of x is const(T). Which means for reference types, 'x' is modifiable but what it references is not modifiable. And for non-reference types, 'x' is not modifiable. So in some cases 'x' can be changed but in some cases it can't. Is that going to be a problem? const int x; // Can't change 'x' const int[] y; // Can change 'y' but not y[n] > That leaves what to do about manifest constants. It occurs that we > already have a mechanism for them - enums. So why not: > enum x = 3; > enum long y = 4; > ? I think that solves our problem. An additional requirement, I guess, was to avoid creating a new keyword. In that case, the 'alias' keyword could also be overloaded to perform this role. alias x = 3; alias long y = 4; alias real pi = 3.14159265358979; especially in syntax forms that 'enum' would have problems with ... alias { x = 3; long y = 4; real pi = 3.14159265358979; } > There's one last problem: > class C { } > const(C)[] a; > a[3] = new C(); // error, x[3] is const I see, but in the new regime, doesn't this mean that both 'a' and what it refers to are const? Or would that be written ... const ( (C)[]) a; and thus what does this mean ... const (C[]) a; To summarize, we can write ... const C[] a; const (C)[] a; const (C[]) a; const ((C)[]) a; What will each of these forms signify? -- Derek (skype: derek.j.parnell) Melbourne, Australia 7/12/2007 9:44:43 AM |
December 06, 2007 Re: const again | ||||
---|---|---|---|---|
| ||||
Posted in reply to Janice Caron | Janice Caron wrote: > On 12/6/07, Walter Bright <newshound1@digitalmars.com> wrote: >> There are a couple problems with it, the worst of which is its impact on >> generic code: >> const(T)[] >> Would you put the & there or not? > > Good point. You'd need it for a class, but not for a struct. I hadn't > thought of that. > > That said, would that be much of a problem? I think it would be, especially from the point of view of generic programming. > Arrays of structs are very > different beasts from arrays of class references. The copy semantics > alone are different enough that one might imagine that generic code > would need one or two if(is(T==struct))s in there anyway. The less of such special casing the better <g>. >> What would & mean if one wrote: >> struct S { C c; } >> const(S)&[] a; >> ? > > I had in mind that that would be a syntax error. A special syntax for class types means that one has to know that type T is a class. >> One principle we try to adhere to is that it should make sense to be >> able to wrap any type with a struct, and have it be possible for that >> struct to behave as if it were that member type. > > If we went with the & syntax, then that principle would dictate the > requirement of an additional operator overload, which for want of a > better name I shall temporarily call opAmpersand. You see how pulling on that string brings us more and more special cases and problems :-( I won't say this is impossible, but it's always something we can think about later after we have more experience with const. >> And finally, this suggests that & means "tail-const". > > I prefer to think that it means "reference to", in the same way that * > means "pointer to". However, this is D, not C++, so the symbol would > only be allowed for types which were /already references/, in which > case it could be used to indicate tail constness by placing the symbol > outside the brackets. Note that const(C&) would mean exactly the same > thing as const(C) - so it's not the ampersand that means tail-const, > it's its placement. > > >> Tail-const has >> that severe problem that there is no such thing as a tail-const member >> function (i.e. a member function that can modify the fields of the >> object, but not anything those fields refer to). > > Forgive me - perhaps I haven't thought this through deeply enough. I > don't follow why that's a problem. If one has a tail-const struct, do you call the mutable member function or the const member function? |
December 06, 2007 Re: const again | ||||
---|---|---|---|---|
| ||||
Posted in reply to Christopher Wright | Christopher Wright wrote: >> I've given up on tail const in any of its forms. The new regime has no tail const, no head const, it's just const, and fully transitive const at that. > > So if I have: > const(Foo)* t; > the pointer is const and points to a const Foo? No, it is a mutable pointer to a const Foo. A const pointer to a const Foo would be: const(Foo*) t; > What about this: > template Ptr(T) { > alias T* Ptr; > } > Ptr!(const(Foo)) t; > > If I have a template method that says: > void Something (T)() { > T[] stuff = new T[5]; > stuff[2] = T.init; > } > Something!(const(Foo)); > > Will that fail? Yes, because T[] will be the same thing as const(Foo)[]. Hiding it behind an alias and a template won't change that <g>. |
December 06, 2007 Re: const again | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter Bright | On 12/6/07, Walter Bright <newshound1@digitalmars.com> wrote: > A special syntax for class types means that one has to know that type T is a class. and > If one has a tail-const struct, do you call the mutable member function or the const member function? Got it. I don't have a solution yet, but at least I know what to think about. If we can't have mutable-ref-to-const-class at all, as you say, it's not so bad. I'd say we can live without that. There are always other ways to code things. But I'll keep thinking. Thanks. |
December 06, 2007 Re: const again | ||||
---|---|---|---|---|
| ||||
Posted in reply to Sean Kelly | Sean Kelly wrote:
> One thing that concerns me. If we assume that "enum x = 3" is simply shorthand for "enum { x = 3 }" then all such declarations would be implicitly typed as integers, which doesn't sound like you want. It seems you're suggesting "enum" be treated more like a storage class here? I'm not sure if I like that idea.
Why not
macro x = 3;
?
|
December 06, 2007 Re: const again | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ary Borenszweig | Ary Borenszweig wrote:
> Sean Kelly wrote:
>> One thing that concerns me. If we assume that "enum x = 3" is simply shorthand for "enum { x = 3 }" then all such declarations would be implicitly typed as integers, which doesn't sound like you want. It seems you're suggesting "enum" be treated more like a storage class here? I'm not sure if I like that idea.
>
> Why not
>
> macro x = 3;
Assuming that we need a new keyword, I like "macro" better. We're going to get it in 2.0 anyway, right?
Sean
|
December 06, 2007 Re: const again | ||||
---|---|---|---|---|
| ||||
Posted in reply to Sean Kelly | Sean Kelly wrote:
> Ary Borenszweig wrote:
>> Sean Kelly wrote:
>>> One thing that concerns me. If we assume that "enum x = 3" is simply shorthand for "enum { x = 3 }" then all such declarations would be implicitly typed as integers, which doesn't sound like you want. It seems you're suggesting "enum" be treated more like a storage class here? I'm not sure if I like that idea.
>>
>> Why not
>>
>> macro x = 3;
>
> Assuming that we need a new keyword, I like "macro" better. We're going to get it in 2.0 anyway, right?
That's the idea. ;-)
There a good use right there for that keyword.
|
December 06, 2007 Re: const again | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter Bright | totally random though: I'm designing a program and ran across a place where I want to say "this pointer shall never be dereferenced, it shall only be used as an identity" the idea being that I want to be sure that the code has no dependencies on anything under it. It would be used somthing like a key in a hash table but where the test is "same thing" not "equal things". What should this be implemented as? Does this have any place in the const system? Is there an existing clean solution? I'm putting this out more as food for though than as a serious suggestion or request for thoughts on how to implement stuff in my case. |
December 06, 2007 Re: const again | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter Bright | Walter Bright Wrote:
> That leaves what to do about manifest constants. It occurs that we
> already have a mechanism for them - enums. So why not:
> enum x = 3;
> enum long y = 4;
> ? I think that solves our problem.
Rather than re-using enum (and confusing me) why not use 'define' eg:-
define x = 3;
define long y = 4;
You can then
a) emphasise 'definite' in the docs: "Having distinct limits", "Indisputable; certain", "Clearly defined; explicitly precise"
while
b) comforting C users.
|
December 07, 2007 Re: const again | ||||
---|---|---|---|---|
| ||||
Posted in reply to Sean Kelly | Sean Kelly wrote: > I can't say I'm terribly fond of using "enum" for this, but it is certainly closer than any other language feature to what you want. However, I am still questioning the need for a new keyword here. Is it that the user may sometimes want type inference to pick up the const qualifier and not other times? Yes for that reason, and the other reason is one rarely wants storage allocated for manifest constants. windows.d has 10,000 declarations in it, who wants 40K of executable bloat from const declarations? > Or would they never want the const qualifier to be picked up? That was my thought, but this has two fatal problems with it: 1) you have to pick up the const qualifier if it's a struct, because the struct may wrap a class reference. Thus, structs would not behave like the underlying types. 2) Andrei pointed out that C++ (which drops the 'head const') is having severe problems with template metaprogramming over this, i.e. it becomes impractical to write "forwarder templates". > If it's the former, then perhaps some rule could be established where the user would never want const to be preserved? For example, I can't see ever wanting it for basic data types like integers, but I might generally want it for classes. I suppose what I'm wondering is if this may be one instance where the ideas of head and tail const apply without causing too many problems? Unfortunately, they do cause problems. For example, struct S1 { int x; } struct S2 { int* p; : What does const mean for S1 and S2? Should it be stripped for one and not the other? |
Copyright © 1999-2021 by the D Language Foundation