View mode: basic / threaded / horizontal-split · Log in · Help
June 22, 2007
Re: D const design rationale
Walter Bright wrote:
> http://www.digitalmars.com/d/const.html

So in short, 'const' protects data and 'final' freezes references.  How 
do these two apply to an int declaration?

    const final int x = 5;

Is either a compiler error? are they synonyms in this case?

This aspect of the design seems very straightforward, aside from the 
question above.  What bothers me, however, is the use of 'invariant'. 
Adding a third keyword simply to represent data that's "really really 
const" just confuses things to me, and I haven't been able to get past 
this.  Given that adding a third keyword doubles the number of 
permutations for describing const behavior, I think the addition of 
'invariant' should be very carefully considered.  Is there any way we 
could get along without it?  I realize that 'invariant' would be rarely 
used in practice, but that doesn't change the impact an additional 
attribute has on the complexity of this design.

Frankly, I think we could almost get away with one keyword, but for the 
fact that D doesn't use a reference qualifier for class references. 
About the only workaround I could think of to describe a const reference 
to mutable data would be something like this:

    const (ref MyClass) x;

And inserting the 'ref' seems even more confusing than simply having 
'final' as in the current design.


Sean
June 22, 2007
Re: D const design rationale
Sean Kelly wrote:
> Walter Bright wrote:
>> http://www.digitalmars.com/d/const.html
> 
> So in short, 'const' protects data and 'final' freezes references.  How 
> do these two apply to an int declaration?
> 
>     const final int x = 5;
> 
> Is either a compiler error? are they synonyms in this case?

It's not an error, it's just redundant.


> This aspect of the design seems very straightforward, aside from the 
> question above.  What bothers me, however, is the use of 'invariant'. 
> Adding a third keyword simply to represent data that's "really really 
> const" just confuses things to me, and I haven't been able to get past 
> this.

invariant = the data doesn't change
const = the data cannot be changed through this reference to it

> Given that adding a third keyword doubles the number of 
> permutations for describing const behavior, I think the addition of 
> 'invariant' should be very carefully considered.  Is there any way we 
> could get along without it?  I realize that 'invariant' would be rarely 
> used in practice, but that doesn't change the impact an additional 
> attribute has on the complexity of this design.

In C++, sometimes const means invariant, and sometimes it means readonly 
view. I've found even C++ experts who don't know how it works.


> Frankly, I think we could almost get away with one keyword, but for the 
> fact that D doesn't use a reference qualifier for class references. 
> About the only workaround I could think of to describe a const reference 
> to mutable data would be something like this:
> 
>     const (ref MyClass) x;
> 
> And inserting the 'ref' seems even more confusing than simply having 
> 'final' as in the current design.

C++ tries too hard to use one keyword to do it all. The result is, as 
the article showed, serious difficulties.
June 22, 2007
Re: D const design rationale
Walter Bright wrote:
> http://www.digitalmars.com/d/const.html

It's a good article. However, it could really use some examples. The article on 
scope was very convincing because it gives plausible use-cases. In particular, I 
think there needs to be an example for 'invariant'. When is 'const' not good enough?
Where you state that invariant solves the aliasing problem, you could prove it 
by rewriting the example from the C++ section.

QUOTE ---
But there is a need for a constant declaration referencing a mutable type.This 
is provided with the final storage class for declarations...Its main purpose is
...[that it]...can be mentally separated from variable declarations that are 
meant to change
---
I don't find this very convincing. Is the mental benefit really significant 
enough to justify the extra complexity? The existence of three const-related 
keywords is pretty tough on mental space!

QUOTE ----
int x = 3;
const int *p = &x;
*p = 4;		// error, read-only view
x = 5;		// ok
int y = *p;	// y is set to 5

This is one instance of the so-called aliasing problem, since while the above 
snippet is trivial, the existence of such aliases can be very hard to detect in 
a complex program. It is impossible for the compiler to reliably detect it. This 
means that the compiler cannot cache 4 in a register and reuse the cached value 
to replace *p, it must go back and actually dereference p again.
---
Shouldn't that be: "the compiler cannot cache 3 in a register" ?
June 22, 2007
Re: D const design rationale
After reading the articles by Walter referred to recently, I'm less confused 
that I was, but would still appreciate some further explanation.

So should "const foo bar = baz" be an error if foo is a value type, on the 
basis that one should be using "invariant" or maybe final? It it safe to 
have two things const/invariant that become identical depending on type?

And does "final" exist *solely* so that you can approximate "invariant" for 
objects as well as for structs and scalars? I can see its use when you want 
something to be invariant but with the stipulation that it must exist in 
memory and have an address. In which case, why have final vs invariant at 
all, rather than having final be, for example, "weak invariant" or "stored 
invariant" or something like that? From here, final just looks 
*semantically* like "a poor man's invariant".
June 22, 2007
Re: D const design rationale
Don Clugston wrote:
> QUOTE ----
> int x = 3;
> const int *p = &x;
> *p = 4;        // error, read-only view
> x = 5;        // ok
> int y = *p;    // y is set to 5
> 
> This is one instance of the so-called aliasing problem, since while the
> above snippet is trivial, the existence of such aliases can be very hard
> to detect in a complex program. It is impossible for the compiler to
> reliably detect it. This means that the compiler cannot cache 4 in a
> register and reuse the cached value to replace *p, it must go back and
> actually dereference p again.
> ---
> Shouldn't that be: "the compiler cannot cache 3 in a register" ?

No. At "*p = 4;" the compiler can't cache 4, because then at "int y = *p;" y
would become 4 instead of 5.

Although in the example it's moot because "*p = 4;" is an error.

-- 
Remove ".doesnotlike.spam" from the mail address.
June 22, 2007
Re: D const design rationale
Deewiant wrote:
> Don Clugston wrote:
>> QUOTE ----
>> int x = 3;
>> const int *p = &x;
>> *p = 4;        // error, read-only view
>> x = 5;        // ok
>> int y = *p;    // y is set to 5
>>
>> This is one instance of the so-called aliasing problem, since while the
>> above snippet is trivial, the existence of such aliases can be very hard
>> to detect in a complex program. It is impossible for the compiler to
>> reliably detect it. This means that the compiler cannot cache 4 in a
>> register and reuse the cached value to replace *p, it must go back and
>> actually dereference p again.
>> ---
>> Shouldn't that be: "the compiler cannot cache 3 in a register" ?
> 
> No. At "*p = 4;" the compiler can't cache 4, because then at "int y = *p;" y
> would become 4 instead of 5.
> 
> Although in the example it's moot because "*p = 4;" is an error.
In which case the example doesn't demonstrate anything. <g>

Better, I think, would be:
int x = 3;
const int *p = &x;
*p = 4;        // error, read-only view
int y = *p;
x=5;
int z = *p;

and then compiler can't set z=y.
Then we can see what invariant is for:

int x = 3;
invariant int *p = &x; // error, x is not invariant


invariant int x = 3;
invariant int *p = &x;
*p = 4;        // error, p is invariant
int y = *p;
x=5;           // error, x is invariant
int z = *p;
// compiler knows that y==z.
June 22, 2007
Re: D const design rationale
Walter Bright, el 22 de junio a las 01:07 me escribiste:
> Sean Kelly wrote:
> >Walter Bright wrote:
> >>http://www.digitalmars.com/d/const.html
> >So in short, 'const' protects data and 'final' freezes references.  How do these two apply to an int declaration?
> >    const final int x = 5;
> >Is either a compiler error? are they synonyms in this case?
> 
> It's not an error, it's just redundant.

Shouldn't be better to be an error? So it's more clear that final makes
sense only for reference types.

Even more, aren't:

const int x = 5;
final int x = 5;
invariant int x = 5;

all the same?

-- 
LUCA - Leandro Lucarella - Usando Debian GNU/Linux Sid - GNU Generation
------------------------------------------------------------------------
E-Mail / JID:     luca@lugmen.org.ar
GPG Fingerprint:  D9E1 4545 0F4B 7928 E82C  375D 4B02 0FE0 B08B 4FB2 
GPG Key:          gpg --keyserver pks.lugmen.org.ar --recv-keys B08B4FB2
------------------------------------------------------------------------
No existe nada más intenso que un reloj, ni nada más flaco que una
bicicleta. No intenso como el café, ni flaco como escopeta.
	-- Ricardo Vaporeso
June 22, 2007
Re: D const design rationale
Leandro Lucarella wrote:
> Walter Bright, el 22 de junio a las 01:07 me escribiste:
>> Sean Kelly wrote:
>>> Walter Bright wrote:
>>>> http://www.digitalmars.com/d/const.html
>>> So in short, 'const' protects data and 'final' freezes references.  How do these two apply to an int declaration?
>>>    const final int x = 5;
>>> Is either a compiler error? are they synonyms in this case?
>> It's not an error, it's just redundant.
> 
> Shouldn't be better to be an error? So it's more clear that final makes
> sense only for reference types.

Allowing it allows cleaner generic code, otherwise templates would often 
have to check whether parameters were value or reference types.
June 22, 2007
Re: D const design rationale
Frits van Bommel wrote:
> Leandro Lucarella wrote:
>> Walter Bright, el 22 de junio a las 01:07 me escribiste:
>>> Sean Kelly wrote:
>>>> Walter Bright wrote:
>>>>> http://www.digitalmars.com/d/const.html
>>>> So in short, 'const' protects data and 'final' freezes references. 
>>>> How do these two apply to an int declaration?
>>>>    const final int x = 5;
>>>> Is either a compiler error? are they synonyms in this case?
>>> It's not an error, it's just redundant.
>>
>> Shouldn't be better to be an error? So it's more clear that final makes
>> sense only for reference types.
> 
> Allowing it allows cleaner generic code, otherwise templates would often
> have to check whether parameters were value or reference types.

Indeed; we already need to special-case functions that return void.  "It
can't be *that* bad!"  In some cases, it means an entire template has to
be duplicated *just* for the void case.  I had to do this for a
coroutine implementation, and was not happy about it.

	-- Daniel
June 22, 2007
Re: D const design rationale
Walter Bright wrote:
> Sean Kelly wrote:
>> Walter Bright wrote:
>>> http://www.digitalmars.com/d/const.html
>>
>> So in short, 'const' protects data and 'final' freezes references.  
>> How do these two apply to an int declaration?
>>
>>     const final int x = 5;
>>
>> Is either a compiler error? are they synonyms in this case?
> 
> It's not an error, it's just redundant.

Okay, thanks.

>> This aspect of the design seems very straightforward, aside from the 
>> question above.  What bothers me, however, is the use of 'invariant'. 
>> Adding a third keyword simply to represent data that's "really really 
>> const" just confuses things to me, and I haven't been able to get past 
>> this.
> 
> invariant = the data doesn't change
> const = the data cannot be changed through this reference to it

And a 'const' at the declaration point implicitly means 'invariant'.

>> Given that adding a third keyword doubles the number of permutations 
>> for describing const behavior, I think the addition of 'invariant' 
>> should be very carefully considered.  Is there any way we could get 
>> along without it?  I realize that 'invariant' would be rarely used in 
>> practice, but that doesn't change the impact an additional attribute 
>> has on the complexity of this design.
> 
> In C++, sometimes const means invariant, and sometimes it means readonly 
> view. I've found even C++ experts who don't know how it works.

Odd.  The C++ system always seemed extremely simple to me.

>> Frankly, I think we could almost get away with one keyword, but for 
>> the fact that D doesn't use a reference qualifier for class 
>> references. About the only workaround I could think of to describe a 
>> const reference to mutable data would be something like this:
>>
>>     const (ref MyClass) x;
>>
>> And inserting the 'ref' seems even more confusing than simply having 
>> 'final' as in the current design.
> 
> C++ tries too hard to use one keyword to do it all. The result is, as 
> the article showed, serious difficulties.

I personally find the use of three keywords to represent three 
overlapping facets of const behavior to be very confusing, and am 
concerned about trying to explain it to novice programmers.  With three 
keywords, there are six possible combinations:

final
const invariant
final const
final invariant
const invariant
final const invariant

That some of these may be redundant just serves to further confuse the 
issue in my opinion.  So I wondered whether one of the keywords could be 
done away with.  Previously, you said 'invariant' may only apply to data 
whose value can be determined at compile-time, thus I imagine it can 
only apply to concrete/data types (ie. not classes).  Assuming this is 
true, I wonder whether there is truly a point in having 'invariant' at 
all.  Assuming it were done away with, the system becomes much simpler 
to me:

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?).


Sean
1 2 3 4 5 6
Top | Discussion index | About this forum | D home