March 20, 2007
On Tue, 20 Mar 2007 14:03:34 -0700, Andrei Alexandrescu (See Website For
Email) wrote:

> Walter Bright wrote:
>> Lionello Lunesu wrote:
>>> I understand, but what's the point of telling the compiler "I don't want to rebind this variable"? It doesn't seem like an optimization hint. Like telling "func(const int i)" in C++ doesn't actually do anything. You just type more.
>> 
>> Final is handy for a number of things:
>> 1) For class members, it would indicate that a class is not mutable once
>> it's constructed. Probably most classes are like this, and so it's a
>> handy way to document it.
>> 2) Andrei pointed out to me that one can often replace:
>>     auto x = initializer;
>> with:
>>     final x = initializer;
>> to indicate in a block of code that x will never be reassigned. This
>> aids in understanding the code. It's a style I intend to adopt.
> 
> And the compiler will have an excellent opportunity to optimize the code (e.g. it can enregister "x" without fear). It's a win-win deal. Believe me. I'm not wearing a tie.
> 
>> 3) For cases like:
>>     const char[] s = "hello";
>> is it s that's not rebindable, or is the data that s is pointing to
>> immutable? This never fails to confuse me (in C++), so I like to be able
>> to say which it is in a clear manner.
> 
> What still needs to be decided here is whether we want to automatically make s final too when seen in a data definition. This is a hack for existing code's sake, and also because many people actually mean to make final const strings more often than just nonfinal const strings. Probably final can be inferred via simple flow analysis at low or no extra cost, which would please everyone.

Now I know (really) that new keywords are *to be avoided at all costs*, but
this looks nice to me ...

   literal char[] s = "hello";

meaning that neither 's' can be changed nor can the data 's' points to.

-- 
Derek
(skype: derek.j.parnell)
Melbourne, Australia
"Justice for David Hicks!"
21/03/2007 10:17:22 AM
March 20, 2007
Derek Parnell wrote:
> On Tue, 20 Mar 2007 16:52:14 +0100, Frits van Bommel wrote:
> 
>> Stewart Gordon wrote:
>>> Tyler Knott Wrote:
>>>> Lionello Lunesu Wrote:
>>>>> What's the use of "final" for variables?  I'm saying "for variables" because for methods the benefit is only too clear.
>>>> Because the "const" keyword is being repurposed for read-only references to mutable or non-mutable data, we need a new keyword for non-mutable variables.
>>> <snip>
>>>
>>> C++ manages with const for both, so why can't D?  What circumstance is there in which either keyword would be valid with different meanings?
>> If you apply "const" to a class reference, how would you determine which of {reference,object} the const applies to?
>>
>> - If to the reference only, you can't express the constness of objects.
>> - If to the object only, you can't express non-rebindability of the reference. (C++ doesn't have this problem, since the only references it has are implicitly final all by themselves)
>> - If to both, you can only express constness of objects by simultaneously disallowing the reference to be rebound. Not nice.
>>
>> I think that covers all cases (except 'neither', but that simply doesn't make any sense ;) ).
> 
> What happens with ...
> 
>    final const Foo f;
>    invariant Foo f;
> 
> do either of these mean that both the reference and the object is not to be
> modified?
> 

In the first decleration, the referance cannot be changed, and provides only an immutable view into the object, so the object cannot be modified /by/ the referance 'f'.  It is a final variable, of type const Foo.

In the second decleration, the referance is mutable, but the object is guaranteed unchanging.  It is a standard variable, of type invariant Foo.

If you wanted to absolute guarantee that 'f' itself never changes, and the underlying object does likewise, it'd be: final invariant Foo f;

If I'm following all this right...

-- Chris Nicholson-Sauls
March 20, 2007
On Tue, 20 Mar 2007 18:19:29 -0600, Chris Nicholson-Sauls wrote:

> If you wanted to absolute guarantee that 'f' itself never changes, and the underlying object does likewise, it'd be: final invariant Foo f;

At which point I'd wish for a text macro system to make "guard" the alias for "final invariant" <G>

   guard Foo f;

-- 
Derek
(skype: derek.j.parnell)
Melbourne, Australia
"Justice for David Hicks!"
21/03/2007 10:34:41 AM
March 21, 2007
"Walter Bright" <newshound@digitalmars.com> wrote in message news:etpb8a$bfe$1@digitalmars.com...
> Lionello Lunesu wrote:
>> I understand, but what's the point of telling the compiler "I don't want to rebind this variable"? It doesn't seem like an optimization hint. Like telling "func(const int i)" in C++ doesn't actually do anything. You just type more.
>
> Final is handy for a number of things:
> 1) For class members, it would indicate that a class is not mutable once
> it's constructed. Probably most classes are like this, and so it's a handy
> way to document it.

Yeah, I see now how that would be handy. It's C#'s "readonly".

> 2) Andrei pointed out to me that one can often replace:
> auto x = initializer;
> with:
> final x = initializer;
> to indicate in a block of code that x will never be reassigned. This aids
> in understanding the code. It's a style I intend to adopt.

OK, "final x" means that you can skip big pieces of code, knowing that "x" will not change.

> 3) For cases like:
> const char[] s = "hello";
> is it s that's not rebindable, or is the data that s is pointing to
> immutable? This never fails to confuse me (in C++), so I like to be able
> to say which it is in a clear manner.

Will "const" imply "final"? Hm, guess not, since you'll still want to write "const char* x" and reassign 'x' later. But now I'm thinking too much C++.

>> And if you later want to rebind 'i' you'll have to change the interface. Lose-lose?
>
> Although final is specified in the interface, it is not part of the interface. It only affects the implementation of the interface. You'll be able to change it without affecting any users of the interface.

Ah, that alone makes it a lot more practical than (half of) C++'s const. Good one.

Some good points. Thanks.

L.


March 21, 2007
Walter Bright wrote:
> Lionello Lunesu wrote:
>> And if you later want to rebind 'i' you'll have to change the interface. Lose-lose?
> 
> Although final is specified in the interface, it is not part of the interface. It only affects the implementation of the interface. You'll be able to change it without affecting any users of the interface.

Same as C++ here then: the declaration

void f(int);

is identical to

void f(int const);

though in the corresponding definition the implementation
gets checking that it doesn't alter its local copy of the
int if it uses const qualification.  It's quite legal
(and quite common) to declare

void f(int);

and then define f as

void f(int const value)
{
  // ... code here can't accidentally change the local value
}

-- James
March 21, 2007
Lionello Lunesu wrote:
> I've been trying to follow the thread on the const/final/invariant extensions but I have to wonder: how useful are final variables?
> [...]

If you spend any amount of time writing Java code, you can appreciate 'final' fairly easily.  In Java, String is immutable, so a final String is like a const std::string.  On the other hand, Java provides StringBuilder for mutable operations on strings.  It's a little like std::stringstream, but not quite.

// Create a new StringBuilder and reserve a buffer of at least 48 chars
StringBuilder s = new StringBuilder(48);
s.append("Hello,");
...
s = methodReturningNewStringBuilder();
...
s.append(" world!");
// s.toString() == "Hello, world!"?  Maybe, maybe not

final StringBuilder s = new StringBuilder(48);
s.append("Hello,");
...
s = methodReturningNewStringBuilder(); // Error
...
s.append(" world!");
// s.toString() == "Hello, world!"?  Provably!

What you can't do in Java is declare a const or invariant StringBuilder.  While this example is a little contrived, once you start talking about file streams and JDBC Statements and ResultSets, knowing whether a variable has been rebound becomes a very big deal.  That is, just declaring a few things 'final' can eliminate a whole host of potential bugs and let you focus on the parts of the code that really matter.

Dave
March 23, 2007
Andrei Alexandrescu (See Website For Email) wrote:
> Benji Smith wrote:
>> Andrei Alexandrescu (See Website For Email) wrote:
>>>> This is the part I'm not sure about. As with C++'s "const", I don't think the compiler can conclude anything and therefor it can't optimize anything. A "final" variable is not constant.
>>>
>>> final int x = 42;
>>>
>>> Change that :o).
>>>
>>> Andrei
>>
>> How does this interact with CTFE for variables that are declared as const. With previous versions of the compiler, I know that it would try to constant-fold this code, resulting in an inlined constant from the result of the CTFE:
>>
>>    const int abc = kaboom();
>>
>> That code shouts out to me (and to the compiler) that the kaboom() method MUST be evaluated at compile-time. But this code is not nearly so clear:
>>
>>    final int xyz = shabam();
>>
>> Just because xyz can't be re-bound after its initial assignment doesn't necessarily mean that shabam() should be executed at compile-time. With the new const/final/invariant semantics, how will the compiler know when to perform constant-folding (or, I suppose, "final-folding") on functions?
> 
> Undecided at this time. At least "static final" will take care of that - you can't dynamically-initialize statics.

But presumably that would allocate space for the variable in the data segment.

int CTFE_function1(int x)
{
	static final y = CTFE_function2(x);
}

And that's a really clumsy construction for something which occurs so frequently.
1 2 3
Next ›   Last »