June 23, 2007
Walter Bright wrote:
> Sean Kelly wrote:
> 
>> Perhaps I misunderstood the "must be known at compile-time" clause.
> 
> That's only when you use invariant as a storage class. It doesn't apply when you use it as a type constructor.
> 
>>  Can 'invariant' apply to dynamic arrays that will remain unchanged once initialized?
> 
> Yes.

Ah, now it's coming clear.  For some reason I thought 'invariant' only worked as a storage class.  I guess my only real issue with the design now is the use of the word 'invariant' -- it's rather long :-)  In some respects I'd almost prefer using 'const' for 'invariant' and 'view' for 'const'.  But I think this suggestion has come up before and 'view' was shot down because it's both a noun and a verb?

>   In my work I use almost no static data--it's all generated
>> on the fly or loaded from some data source.  Will 'invariant' help to make my code more optimal?
> 
> Not with the current compiler, because the back end hasn't been modified to take advantage of it. But the potential is there.

Yeah, I don't care if the compiler does it now, only that the potential is there.  After all, this discussion is about the design, not the implementation.

Thanks for explaining things.  I'm coming to understand the reasoning behind the design you've chosen.


Sean
June 23, 2007
Sean Kelly wrote:
> 
>>> I can appreciate that 'invariant' may be of tremendous use to the compiler, but I balk at the notion of adding language features that seem largely intended as compiler "hints."
>>
>> It's a lot more than that. First, there's the self-documenting aspect of it. Second, it opens the way for functional programming, which can be of huge importance.
> 
> Could you explain?  I've been trying to determine how I would write a library using these new features, and so far, 'invariant' simply seems more an obstacle to maintainability (because of the necessary code duplication), than it is an aid to programming.
> 

In which situation does having 'invariant' lead to code duplication? I can see the common situation where you have class getter methods, or other similiar methods, but even without 'invariant' and only with const and non-const you have that problem.

> 
>>> The compiler can inspect the code however, and a global const is as good as an invariant for optimization (as far as I know).  As for the rest, I think the majority of remaining cases aren't ones where 'invariant' would apply anyway: dynamic buffers whose contents are guaranteed not to change either in word or by design, etc.
>>
>> But they do apply - that's the whole array optimization thing. You're not just going to have global arrays.
> 
> Perhaps I misunderstood the "must be known at compile-time" clause.  Can 'invariant' apply to dynamic arrays that will remain unchanged once initialized?  In my work I use almost no static data--it's all generated on the fly or loaded from some data source.  Will 'invariant' help to make my code more optimal?
> 
> 
> Sean

Of course, that's the whole point of invariant. The 'invariant' keyword is being used for two things, compile-time values, and invariant data. You obviously can't do what you mention with compile-time values, but you can with invariant data (which is created at runtime). (or have I misunderstood you, and you already knew that?)

-- 
Bruno Medeiros - MSc in CS/E student
http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
June 23, 2007
Reiner Pope wrote:
> I think that invariant-as-storage-class vs. const-as-storage-class is a false dichotomy, and also that they are incorrectly associated with the completely different type-constructors, const() and invariant().
> 
> 
> As storage classes, const and invariant both mean "compile-time constant" -- their initializers must be evaluatable at compile time, and their data need not be stored in memory.
> 
> However, apparently, data referred to by const-as-storage-class could actually be liable to change (this is cited as the difference between const-as-storage-class and invariant-as-storage-class).
> 
> Yet this seems to clash with the idea of being initialized at compile time: in order for the data pointed to by const-as-storage-class to be changed by another reference, there must be a mutable pointer from which such a variable is initialized. Something like:
> 
> void main() {
>    int a = 10;
>    int* p = &a; // here's our mutable view
>    const int* cp = &a; // here's our const-as-storage-class
> }
> 
> At the moment, this doesn't compile, because &a is not evaluatable at compile time (even though the address of a is statically known). Assuming this is never supported (and I don't think that it should be), then the data pointed to by a const-storage-class variable can never be changed, so the data is really invariant. In that case, const-as-storage-class should be abolished, as it is identical to invariant-as-storage-class.[1]
> 
> ---

I agree. Since in D, compile time values cannot be altered at compile time, then any compile time value is immutable/invariant. Thus const-as-storage-class is the same as invariant-as-storage-class and those concepts should be cleared up.

> 
> I also think that the idea of a "compile time constant" is distinct from invariant-as-type-constructor. For the purposes of clarity, I think it would ideally be better to make this distinction clear, and give this storage class a different name (sorry about Yet Another Keyword). I think 'define' could make sense:
> 
>     define PI = 3.14;
>     define LanguageName = "D Programming Language";
> 
> This also emphasises the similarity in meaning to #define.
> 
> Of course, typeof(LanguageName) == invariant(char[])
> 
> ---
> 

I agree. I don't like this overloading of concepts very much, such that 'invariant' is used both for compile time values, and invariant data. It's quite similiar to 'const' keyword in D 1.0, where it was used both for compile time values, and final values.
As for an actual alternative, maybe instead of 'define' we could simply use alias:
Either:
  alias PI = 3.14;
or
  alias 3.14 PI;
In any case, using 'alias' that way is actually pretty consistent with the current meaning of 'alias'.



-- 
Bruno Medeiros - MSc in CS/E student
http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
June 23, 2007
Bill Baxter wrote:
> Walter Bright wrote:
>> http://www.digitalmars.com/d/const.html
> """
> But there is a need for a constant declaration referencing a mutable type.
> """
> 
> Also in the discussion of final, the word that always comes to my mind is 'binding'.  It's the binding of the variable name to its value that's final.   You say, "A final declaration, once it is set by its initializer or constructor, cannot ever change its value for its lifetime."  which to me is kind of vague.  I not sure what it means that "a declaration cannot change its value".  Does a declaration even have a value?  "I'm setting this declaration to 5" -- seems like unusual terminology to me.
> 
> 

I highly agree. That terminology usage made me grind my teeth when reading the article! A declaration "having a value"/"referencing a mutable type"? It's not just unusual, it's plain nonsensical!
'Binding' is better, but I'm also not 100% keen on it. I've been using terms such as 'top-level type', and also 'immediate value'.
BTW, the 'immediate value' of a variable/expression is what I call, by definition: the value that changes when an assignment is made to that variable/expression.
I've found that in Walter's article, when he mentions "declaration", in most cases he means either 'top-level type', or 'immediate value'.

-- 
Bruno Medeiros - MSc in CS/E student
http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
June 23, 2007
Daniel Keep wrote:
> 
> Sean Kelly wrote:
>> ...
>>
>> final
>> const
>> final const
>>
>> And that's it.  'final' means a reference cannot be rebound, 'const'
>> means the data cannot be altered (through the reference), and 'final
>> const' means that both the reference is frozen and the data cannot be
>> changed.  And that's it.  That the existence of invariant required the
>> addition of parenthesis on class invariants just serves to strengthen
>> the argument in my mind.  So in short, I'm just not convinced that
>> 'invariant' provides enough utility to warrant the cost in complexity
>> and broken consistency (unittest doesn't require parens, so why does
>> invariant?).
> 
> What makes me uneasy about the above is that final isn't a type
> constructor: it's a storage class.  You're turning it into
> sorta-kinda-but-not-quite both.  So, you end up with:
> 
> final int x;		typeof(x) == int;
> const int y;		typeof(y) == const int;
> final const int z;	typeof(z) == final const int;
> 

And in what are you based to say that those typeofs are like that?
The typeof of each of those 3 vars is int (as reported by DMD). And in terms of semantics y and z are exactly the same, only x differs from those other two (y and z, are compile-time values, with all that that implies).



-- 
Bruno Medeiros - MSc in CS/E student
http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
June 23, 2007
Walter Bright wrote:
> Sean Kelly wrote:
>> However, my point was that to a programmer, optimization should be invisible.
> 
> I can't agree with that. The compiler and the programmer need to cooperate with each other in order to produce fast programms. If a programmer just throws the completed program "over the wall" to the optimizer and expects good results, he'll be sadly disappointed.
> 
> 
>> I can appreciate that 'invariant' may be of tremendous use to the compiler, but I balk at the notion of adding language features that seem largely intended as compiler "hints."
> 
> It's a lot more than that. First, there's the self-documenting aspect of it. Second, it opens the way for functional programming, which can be of huge importance.
> 
> 
>> Rather, it would be preferable if the language were structured in such a way as to make such hints unnecessary.
> 
> That would be preferable, but experience with such languages is that they are complete failures at producing fast code. Fast code comes from a language that enables the programmer to work with the optimizer to produce better code.
> 
> Lots of people think that just 'cuz they write in C++, which has good optimizers available, they'll get fast code. That's not even close to being true.
> 
> 
>> To that end, and speaking as someone who isn't primarily involved in numerics programming, my impression of FORTRAN is that the language is syntactically suited to numerics programming, while C++ is not.  Even if C++ performed on par with FORTRAN for similar work (and Bjarne suggested last year that it could), I would likely still choose FORTRAN over C++ because the syntax seems so much more appealing for that kind of work.
> 
> I programmed for years in FORTRAN. The syntax is not appealing, in fact, it sucks. The reason it is suited for numerics programming is because FORTRAN arrays, by definition, cannot be aliased. This means that optimizers can go to town parallelizing array operations, which is a big, big deal for speed.
> 
> You can't do that with C/C++ because arrays can be aliased. I have a stack of papers 6" deep in the basement on trying to make C more suitable for numerics, and it's mostly about, you guessed it, fixing the alias problem. They failed.

How much of this will actually be solved by invariant?
It seems to me that typically, arrays are built up element-by-element, even if they never change again. I guess in D2.0, such code would initialize a temporary array, and finally idup it?

The aliasing problem will be far from gone, though. Consider an in-place operation on a matrix. Frequently you modify one only row at a time, based on the remaining rows. I think you'd have to cast(invariant) those other rows, to avoid aliasing.

> There are some template libraries for C++ which parallelize array operations and can finally approach FORTRAN. But they are horrifically kludgy and complicated. No thanks. But the effort that has gone into them is astonishing, and is indicative of how severe the problem is.

Actually in C++ I think there's a problem with operator overloading, not just a problem with const. Op overloads destroy far too much valuable information. I'll discuss that a bit in my conference presentation.

Interesting thing is, with poor-man's-macros (mixin + ctfe), you can detect a great many cases of aliasing (since two static arrays are guaranteed not to alias each other). And you can also assert that there's no overlap between arrays, then generate code assuming no aliasing. Invariant would move that to a compile-time check, but if you had array operations built-in, I'm not sure how much extra benefit it would give (D can do a *much* better job than C++ already).
June 23, 2007
Walter Bright Wrote:

> BLS wrote:
> > I am afraid you will not like this idea, but not afraid enough. <g>
> > 
> > Why not using a single keyword "const_" adding a number 1, 2, 3 to
> > represent :
> > invariant, final, readonlyview.
> > the higher the number the higher (the stronger) the const.
> > means : const_3 == invariant;
> > At least a mental help, IMO; somehow borrowed from Modula 2 processes.
> 
> You're right, I don't like the idea <g>.

I'm curious. Was 'readonly' or 'readonlyview' considered as an alternative for 'const'? I kind of like the sound of 'readonly', and it doesn't make you think of C++ 'const'... but maybe that's bad.
June 23, 2007
On Sat, 23 Jun 2007 08:32:36 -0700, Sean Kelly wrote:

> Will 'invariant' help to make my code more optimal?

Yeah ... what he said.

I'm with Sean on these points. There seems to be a false dichotomy being peddled here; that optimal run-time performance is mutually exclusive with source code that is cheap to write and maintain.

D is so close to given us both that I constantly scream at the ugly warts that is being instilled into this wonderful language.

I agree that the concepts behind 'const' and 'invariant' represent two different and valid concepts that need to be catered for. The problem is in their proposed implementation. The keywords chosen are a hinderence to D source maintenance because they both appear to mean either of these two concepts. Sure, they will be learned and distingushed in one's mind over time, I've no doubt of that, but that is the problem in itself. Instead, why not use different key words that actually reflect the differences in the two concepts.

A second issue I have is that by forcing 'const' to be explicitly coded in function parameter lists, you are reducing the ability of the compiler to help detect bugs.

-- 
Derek Parnell
Melbourne, Australia
"Justice for David Hicks!"
skype: derek.j.parnell
June 23, 2007
On Sat, 23 Jun 2007 18:22:41 +0100, Bruno Medeiros wrote:

> Of course, that's the whole point of invariant. The 'invariant' keyword is being used for two things  ...

And thus a source of confusion. Overloading keywords is not a smart move.

-- 
Derek Parnell
Melbourne, Australia
"Justice for David Hicks!"
skype: derek.j.parnell
June 23, 2007
On Sat, 23 Jun 2007 18:34:59 +0100, Bruno Medeiros wrote:

> Reiner Pope wrote:
>> 
>> I also think that the idea of a "compile time constant" is distinct from invariant-as-type-constructor. For the purposes of clarity, I think it would ideally be better to make this distinction clear, and give this storage class a different name (sorry about Yet Another Keyword). I think 'define' could make sense:
>> 
>>     define PI = 3.14;
>>     define LanguageName = "D Programming Language";
>> 
>> This also emphasises the similarity in meaning to #define.
>> 
>> Of course, typeof(LanguageName) == invariant(char[])
>> 
>> ---
>> 
> 
> I agree. I don't like this overloading of concepts very much, such that
> 'invariant' is used both for compile time values, and invariant data.
> It's quite similiar to 'const' keyword in D 1.0, where it was used both
> for compile time values, and final values.
> As for an actual alternative, maybe instead of 'define' we could simply
> use alias:
> Either:
>    alias PI = 3.14;
> or
>    alias 3.14 PI;
> In any case, using 'alias' that way is actually pretty consistent with
> the current meaning of 'alias'.

I like both 'define' and 'alias' for this idea. 'alias' is not being overloaded because the concept behind it is retained.

-- 
Derek Parnell
Melbourne, Australia
"Justice for David Hicks!"
skype: derek.j.parnell