March 16, 2007
Andrei Alexandrescu (See Website For Email) wrote:
> Benji Smith wrote:
>> Andrei Alexandrescu (See Website For Email) wrote:
>>> We've shoved keywords like "readonly" and "view" for a while, and they just added more confusion than cleared, at a high cost. If (as I suspect) super const appears relatively infrequently, it might be fine to just encode it as the mildly verbose "super const". In fact, it's shorter than "keepyourgrubbyhandsoff". :o)
>>
>> Really? I'd think super const would be used all the time. Anywhere a class has some invariant field, it'll probably be expressed as super const (if I'm understanding correctly that super const is the equivalent of #define constants in C++ or static final constants in Java).
> 
> No. super const deals with pointers and transitivity. Final deals with non-rebindable symbols. I'd be hard pressed to think of many examples where class members are transitively immutable.

Well this explains a lot.  I'd misunderstood as well.


Sean
March 16, 2007
Walter Bright wrote:
> Benji Smith wrote:
>> Bingo. It's like trying to describe something as "impossible impossible". If the first usage of the word didn't really convey impossibility, then you were using the wrong word to begin with.
> 
> Reminds me of the old assembler program:
> 
>     foo:
>         MOV EAX, 3
>         CALL BAR
>         HALT        ; stop the program
>         HALT        ; if skidding

LOL
March 16, 2007
Sean Kelly wrote:
> Frits van Bommel wrote:
>> Walter Bright wrote:
[snip]
>>> 'readonly' means the data went into ROM. Also, marking a page in a virtual memory system as 'readonly' means that nobody can modify it.
[snip]
>>
>> Oh, and on x86 (and amd64) processors the operating system is allowed to write to 'readonly'[1] pages unless it sets the WP (Write-Protect) bit in system register CR0. Note: as this bit is *off* by default, it needs to be explicitly turned on by the OS.
> 
> So *that's* why Win32 doesn't complain when constant data is modified and pretty much every other OS does.  Good to know.

No I don't think so. The 'WP' bit only applies to kernel-level (ring 0-2) code. Ring 3 code (i.e. normal user-level code) can never write into "readonly" pages. The only explanation I can think of for Win32 allowing writes into a programs read-only data is that the pages aren't marked "readonly" at all for some reason.

Unless of course user-level code is ran somewhere in ring 0-2, but I don't think even Windows would do something so stupidly insecure: that would allow user-level code to read and write anywhere in kernel space, barring segment limits.

(I didn't say Microsoft instead of Windows above, since Microsoft's research division is experimenting with a .NET based OS that *does* run everything in ring 0. However, that uses a different mechanism to ensure safety: programs are checked for type-safety before being allowed to run. That's not really feasible for traditional machine-code based OSs though...)
March 16, 2007
kris wrote:
> Walter Bright wrote:
>> Benji Smith wrote:
>>
>>> Bingo. It's like trying to describe something as "impossible impossible". If the first usage of the word didn't really convey impossibility, then you were using the wrong word to begin with.
>>
>>
>> Reminds me of the old assembler program:
>>
>>     foo:
>>         MOV EAX, 3
>>         CALL BAR
>>         HALT        ; stop the program
>>         HALT        ; if skidding
> 
> LOL

You know those teenagers with the overclocked CPUs...
March 16, 2007
Dan wrote:
> Wow...
> 
> I've never put this much thought into const/final stuff.  Ultimately, the program *cannot* prevent data in memory from being changed.  It can at best prevent you from accidentally changing it; hence final and const declarations mean "I don't want anyone to change these, can you raise an error if someone tries to within D?"
> 
> Also, the problem breaks down to 'what am I declaring const?'.  If I declare:
> 
> const int* x; // is it the pointer, or the int?
> 
> This doesn't seem important until you get to:
> 
> const int[int**][]* x; // now what is it?
> 
> Ultimately, you have this problem going through each and every pointer, array and value.  You could theoretically write this:
> 
> const int[int**][]*[char[]][3][17][3,17]* x;  and now what are you going to do?  declare it:
> 
> final const final final const const final final final final final const?
> Even final const! super const! final! const! doesn't work, in fact I agree it makes it worse.
> 
> Good luck getting readability with that.

This:
  const int[int**][]*[char[]][3][17][3,17]* x;

is *already* unreadable (plus I don't think that [3,17] part is legal D).  If any reasonable programmer really did have a need for such a type then they would probably break it up into aliases with some sort of meaning.

--bb
March 16, 2007
Sean Kelly wrote:
> Andrei Alexandrescu (See Website For Email) wrote:
>> Sean Kelly wrote:
>>> Walter Bright wrote:
>>>> Benji Smith wrote:
>>>>> I should also add that, in my opinion, any design where "const" means something other than "value resolved at compile time and immutable at runtime" would be a mistake.
>>>>
>>>> I hear you. I've always disliked C++'s mutable const.
>>>>
>>>> The most important thing at this stage is not the keyword, however, but getting the design right. Andrei, myself and Bartosz have been to hell and back several times over this over the last few months, and have filled about two notebooks with scribblings. It's a difficult problem.
>>>
>>> I very much agree.  But with little information about how these new flavors of const will work, it seems we're mostly stuck debating how they will look :-)  I'd welcome discussing the former issue, but I suspect that anything which is said here will have already been discussed between you three.
>>>
>>>> There are 3 distinct, and very different, flavors of constant:
>>>>
>>>> 1) rebinding of a value to a name
>>>> 2) a read-only view of a data structure
>>>> 3) a value that never changes
>>>
>>> It seems like #1 is only useful for reference types, which currently means pointers and class handles.
>>
>> #1 is essential for expressing numeric constants.
> 
> Could you please provide an example?

final int x = 42;

>>> Further, I don't think I've ever found a need for this particular class of immutability in C++.  How often does it really matter whether someone can reassign a pointer?
>>
>> Very important. Often you want to bind a pointer to something and make sure nothing can change that.
> 
> Perhaps this should be rewritten as "often one wants to..."  I just said that I have never felt a need for this :-)  Of the times where I've used this feature in C/C++, I think every single time has been simply out of diligence rather than because there was any risk of the pointer actually being reassigned.  A pertinent point to me is that D uses pass-by-value so the chance of a reference being silently reassigned "somewhere in the program" is typically almost nil.  About the only place where this is a real risk is with global variables, and since free functions support the property syntax, the programmer has a ready option to prevent such a reassignment from happening.  Besides, free globals are bad programming style anyway.

I think "final" is mostly useful in class and struct members.

>>> As for the other two, it seems like #3 is a storage class
>>
>> No, because the value may embed pointers that you want to pass to functions. Sorry for sounding dismissive, but we've been all of these dead alleys for so long, it's all green codes: I can see the damn Matrix now. Blonde, brunette, const, final...
> 
> That's fine.  You may have been down all these roads before, but I haven't.  I'm mostly asking to gain a better understanding of some of the background.
> 
>>> while #2 is an attribute on the variable itself.  So #3 implies #2.
>>
>> No. #3 implies #2. If a value is super const, then it can be seen as const. Essentially "const" loses a little of the precision that "super const" has.
> 
> I'm confused.  I said "so #3 imples #2" and you replied "no, #3 implies #2."  What does the "no" signify?

Sorry, I misread your sentence as #2 implies #3.

>>> I haven't given this much thought, but is it truly necessary to have two separate keywords for #2 and #3?
>>
>> It's not! That's what I tried to do all along...
> 
> (see below)
> 
>>> Is this to aid the compiler in optimizing, or is there a perceived value here from a user perspective?
>>
>> It will be absolutely essential for the well-definedness of functional-style threads.
> 
> Okay, that's what I figured, though this seems to contradict what you said above.  So in essence, "super const" is actually necessary in some situations to indicate to the programmer that the data he is manipulating is truly immutable.  I almost feel like this feature should exist separately from the type mechanism, so there was a way to test for this instead.

Then you can't prove correctness statically.

>>>  And is it necessary to distinguish all three by separate keywords?
>>
>> It's not necessary :o).
> 
> So it sounds like it truly isn't necessary to separately distinguish #2 and #3 via type qualifiers.  Is this correct?  I can appreciate the need for both, but I very much do not want all of this to become a confusing mess when applied to actual code.

Much anything else would become a mess when applied to actual code. I think we discussed about two dozens of schemes. They all looked great on paper, at least at first blush. They all did miserably during a test drive.


Andrei
March 16, 2007
Andrei Alexandrescu (See Website For Email) wrote:
> Sean Kelly wrote:
>> Andrei Alexandrescu (See Website For Email) wrote:
>>> Sean Kelly wrote:
>>>> Walter Bright wrote:
>>>>>
>>>>> There are 3 distinct, and very different, flavors of constant:
>>>>>
>>>>> 1) rebinding of a value to a name
>>>>> 2) a read-only view of a data structure
>>>>> 3) a value that never changes
>>>>
>>>> It seems like #1 is only useful for reference types, which currently means pointers and class handles.
>>>
>>> #1 is essential for expressing numeric constants.
>>
>> Could you please provide an example?
> 
> final int x = 42;

I must be missing something here.  I expected this to be the point of 'const'.  In C++ parlance:

int const * const val = 0;
      ^       ^
      |       |
     #2      #1

> I think "final" is mostly useful in class and struct members.

Seems reasonable I suppose.  Will there be any change to "final" as it exists now in D, or is this simply an extension of its meaning?

>> Okay, that's what I figured, though this seems to contradict what you said above.  So in essence, "super const" is actually necessary in some situations to indicate to the programmer that the data he is manipulating is truly immutable.  I almost feel like this feature should exist separately from the type mechanism, so there was a way to test for this instead.
> 
> Then you can't prove correctness statically.

Argh.  Good point.

>> So it sounds like it truly isn't necessary to separately distinguish #2 and #3 via type qualifiers.  Is this correct?  I can appreciate the need for both, but I very much do not want all of this to become a confusing mess when applied to actual code.
> 
> Much anything else would become a mess when applied to actual code. I think we discussed about two dozens of schemes. They all looked great on paper, at least at first blush. They all did miserably during a test drive.

Well... darnit :-)


Sean
March 16, 2007
Andrei Alexandrescu (See Website For Email) wrote:
> sclytrack wrote:
>>> IMHO (b) should be 'readonly' and (c) should be 'const'.
>> [snip]
>>
>> vote++
>>
>>
>> Keywords
>> --------
>>
>> I also think keywords can be written attached to one another.
>> Like if you were to really call it "super const" have it called
>> superconst instead of super_const.
> 
> Yet you write static const not staticconst; public static not publicstatic; static if and not staticif; and so on.
> 
> superconst came up too. But it creates a bad precedent. A healthier precedent is to synthesize phrases, not new keywords, from the existing keywords. Think of "static if" or "final switch". Very beautiful.
> 
>> It is like the foreach_reverse that we have in D. Why not
>> call it foreachreverse instead.
> 
> Probably it's best to call it foreach reverse. It's unambiguous, easy to parse, does not add new keywords, and continues another nice precedent set by extern(language) and by scope(exit).

So you mean foreach(reverse) then?  I do like that!  You're right that it is quite D-like.  Too bad you weren't around back when foreach_reverse was introduced?   ;-)

--bb
March 17, 2007
Andrei Alexandrescu (See Website For Email) wrote:
> Deewiant wrote:
>> Benji Smith wrote:
>>> And the word "super" is now overloaded in two completely unrelated concepts.
>>>
>>
>> Which isn't that rare, see the following link:
>> http://www.prowiki.org/wiki4d/wiki.cgi?LanguageSpecification/KeywordIndex
>>
>> I find the following examples: auto, in, is, mixin, scope, static.
>>
>> I have come to abhor the keyword "static" largely due to the above. Too bad its
>> various uses are unavoidably useful. <g>
>>
>> But I do agree with you, in a way. After writing the following I find my
>> explanation somewhat unclear even to myself, but bear with me.
>>
>> The problem with "super const" is that "super" modifies the other keyword,
>> "const", instead of saying something about the expression/statement/whatever (in
>> this case, the type). Even "static", in all its horror, can be seen as
>> specifying one of "module-level" or "compile-time". The other keywords mentioned
>> above use their English meaning as such an explanation, and so can be understood
>> without too much thought. "super const" would make "super" another "static":
>> lacking context, you can't be sure about about even the general meaning, let
>> alone the one in a specific instance.
>>
>> Upon reflection it may be moot, since one probably rarely cares about keywords'
>> meanings without context, but I'm sure some psychologist could come up with
>> something about intuitiveness which affects coding speed, or whatever.
> 
> Working in NLP myself, I totally disagree. Natural language is rife with homonimy and synonimy, and we're all very, very happy with that. But in this case we don't even have to go that far: "super" is an adjective meaning primarily "of high grade or quality" and qualifies a noun. If there's no noun, you don't know what is "of high grade or quality". It's a fact, and we don't even blink.
> 
> The reality behind super const is that it expresses a stronger form of const. It makes a lot of sense if I dub it "super const" in natural language, to express it in the same way in the programming language. I thought that that's too verbose and devised "const!" as a shortcut (again with obvious conotations in natural language), but I'm thinking of dropping it and let type inference add "super" to "const" whenever it can. That should ensure exactness of the type system without verbosity in source code.
> 
>> I'd be happiest to just get the feature as soon as possible; worrying about
>> keyword semantics can come later. Just like the abominations beginning with
>> "on_scope_". <g>
> 
> Great idea. :o)
> 
> 
> Andrei


If you just want something that sounds like more const than const using existing keywords, there are other options:
  'true const'
  'double const'
  'finally const'
  'is const'
  or
  'is finally super double true const'

I kinda like 'true const' myself.  Sounds less dorky than super const to me.
:-)

--bb
March 17, 2007
Andrei Alexandrescu (See Website For Email) wrote:
> Deewiant wrote:
> [snip]
> 
>> In general, I do agree with your view, found elsewhere in the thread, that using
>> existing keywords is best. That, or constructs like "scope (success)" where
>> success isn't a keyword. I'm just currently a bit repelled by the pair "super
>> const".
> 
> Well how about "real const" then :oD.
> 
> I think the good news is that you don't need to type it that often. You type:
> 
> const char[] str = "Hi!";
> 
> and the compiler figures out the "super" part itself.

Doh!  'real const'  of course... how could I leave that one out.


  'real const'
  'true const'
  'double const'
  'finally const'
  'is const'
  or
  'is finally super double true real const'

--bb