Extended Type Design: further examples

Andrei Alexandrescu (See Website For Email) SeeWebsiteForEmail at erdani.org
Mon Mar 19 16:20:04 PDT 2007


Derek Parnell wrote:
> I wish it wasn't so hard to get a simple straight answer from the experts.

It's not like anybody tries to obfuscate their writing.

> So far I think /The W&A Show/ is saying that 'const' and 'invariant' only
> apply to reference data types (objects, variable-length arrays, and
> pointers) and structs. They do not apply *in any way, shape or form* to any
> other data type.
> 
>   const char[] s;    // ok
>   const char   c;    // meaningless, the 'const' is ignored.
>   const classFoo f;  // okay
>   const double* b;   // okay;
>   const double  d;   // meaningless, the 'const' is ignored.
>   const structBar q; // okay
> 
> 'const' means you cannot change the stuff the reference is referencing or
> the members of the struct, *but* for reference types you can change the
> reference value.
> 
>   s[0] = 'a'; // fails
>   s    = "new data"; //ok
>   s.length = 2; // ok
> 
>   c    = 'a'; // ok
> 
>   f.bar = 'a'; // fails
>   f = new classFoo(); // okay
> 
>   *b    = 1.0; // fails
>   b     = &someDouble; // ok
> 
>   d     = 1.0; // okay
> 
>   q.foo = 'a'; // fails

Correct.

> 'invariant' means you cannot change the stuff the reference is referencing
> or the members of the struct, *and* for reference types you cannot change
> the reference value.

No. Invariant means that the data referenced indirectly is never 
modifiable by any part of the program.

What you called 'invariant' above is 'final const'.

[snip]
> However, if this is the interpretation of 'invariant', how does one ever
> get to set the 'invariant' thing's value?
> 
>    invariant byte[] vCodes;
>    . . . 
>    vCodes = LoadCodesFromFile();  // fails, no???

Right now you can only initialize invariant with literals. This aspect 
of the language is still under development. (Things like the result of 
some_string.dup also come to mind.)

>  void func( string s )
>  {
> 
>      string t;
>      char[] u;
>      u = s;
>      u[0] = 'a'; // fails.
>      u = s[1..4];
>      u[0] = 'a'; // fails
>      u = s.dup;
>      u[0] = 'a' // ok
> 
>      t = s; // fails???
> 
>  }

You can't make the assignment u = s.

>> 3. The ~= operator works (somewhat surprisingly).
>  void func( string s )
>  {
>      string t;
>      char[] u;
> 
>      u ~= s; // ok
>      s ~= 'a'; // fails ???
> 
>      t ~= s; // fails???
>  }

s ~= a; works and is equivalent to s = s ~ a, i.e. "rebind s to the 
concatenation of s and a". It's an operation that does not mutate s's 
contents.

>> 4. It's very, very rare that you want to modify some random character in
>> a string, and when you do, use a char[] and then copy it back into a
>> string, or rebuild the string from slices!
> 
> It is not so rare in the type of applications that I do. 

You use char[] for that, and when you are done modifying, you can put 
things in a string.

> Are you saying that I can do this...?
> 
>  string func( string s )
>  {
>      char[] u;
>      u = s.dup;
>      u[somerandomspot] = 'a';
>      return u;
>  }

This is sound, but tricky to typecheck. I'll have to get back to you on 
that one.

> or this ... ?
> 
>  void func( string ref s )
>  {
>      char[] u;
>      u = s.dup;
>      u[somerandomspot] = 'a';
>      s = u;
>  }

Same as above.

> or this ... ?
> 
>  string func( string ref s )
>  {
>      char[] u;
>      string t;
>      u = s.dup;
>      u[somerandomspot] = 'a';
>      t = u;
>  }

These last three examples work because u is temporary and not aliased 
with anything. If it were, the code would be unsound. Such cases are 
tricky to typecheck in the general case, but we'll look into a solution 
that allows such expressive idioms without also taking risks.

> What I don't get here is the phrase "copy it back into a string". This
> sounds ambiguous to me. It could mean, "construct a new string containing
> the updated data", or "replace the original string reference with a
> reference to the updated data". But I was starting to think that
> 'invariant' meant that you couldn't change the reference value at all, so I
> don't see how one could change an 'invariant' parameter or construct an
> 'invariant' local /variable/.

Indeed, 'invariant' meant that the referenced data is invariant. The 
actual variable can be rebound to any other invariant data. It's like 
watching TV: you can always change your choice of watching, but you 
can't modify the actual contents of programs - unless you take special 
measures :o).


Andrei



More information about the Digitalmars-d mailing list