www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - reassign single elements of a string (using foreach)

reply Daniel919 <Daniel919 web.de> writes:
Hi, please look at this code (I discuss the problem below):
--------------------------------------------------------------------
import std.stdio;

void main() {
     string s = "test";

     writefln("s: ", typeid(typeof(s)));

     writefln("s[0]: ", typeid(typeof(s[0])));
     //(s[0]) = 'a'; //Error: s[0] is not mutable

     foreach (ref char c; s) {
         writefln("c: ", typeid(typeof(s[0])));
         c = 'a';
         break;
     }

     writefln(s);

     writefln(typeid(invariant(char[]))); //invariant invariant char[]
     writefln(typeid(invariant(char)[])); //invariant char[]
     invariant(char)[] f;
     writefln(typeid(typeof(f[0]))); //char ????
     //what I expected: invariant(char) like:
     writefln(typeid(invariant(char))); //invariant char
}
--------------------------------------------------------------------
s: const char[]
s[0]: char
c: char
aest
invariant invariant char[]
invariant char[]
char
invariant char

I can use c (within the foreach) to change elements of the string s.
Exactly: I can assign single values of type char to each element of the 
array of invariant chars. (Or I can break after doing so for the n-th 
element)

But I can't use s[0] to do the same for exactly one element.


The funny thing is: c and s[0] are of the same type ! Both are char.

Lets take a look at string, which is an alias for invariant(char)[].
What this means: A mutable array of chars (each char can be reassigned, 
because of the brackets).
"invariant(char) c;" means: You can assign an other value of type char to c.
(PS: On the docs it should be mentioned, that invariant(builtintype) / 
const(builtintype) is useless and behaves like: builtintype)
not to be confused with "invariant char c;" which means: the value of c 
will never change and you can't assign an other value to c.

s[0] is of type char, but to make clear, that you can't assign an other 
char to it, it should be: "invariant char". Then it would be clear, that 
you can't do: s[0] = 'a';

invariant(char[]) -> invariant invariant char[]
                         |        \--------/  |
                          \------------------/

invariant(char)[] -> invariant char[]
                          \------/

So one element would mean the [] to be removed, and the rest is:
invariant(char) -> invariant char

But as I pointed out above, this is not the same.
And that's the reason invariant(char) is always translated to: char
Because it behaves as if it was a normal char (also said above), if you do:
invariant(char) c;
You can assign to it, as if it was just: char c:
c = 'a';

Now take exactly one element of a string,
you get an invariant(char) -> char
But you can't assign an other value of type char to it.

So for arrays it's different, although the type is the same (char).


Daniel
Jul 05 2007
parent Derek Parnell <derek nomail.afraid.org> writes:
On Fri, 06 Jul 2007 03:41:11 +0200, Daniel919 wrote:

 Hi, please look at this code (I discuss the problem below):
 --------------------------------------------------------------------
 import std.stdio;
 
 void main() {
      string s = "test";
 
      writefln("s: ", typeid(typeof(s)));
 
      writefln("s[0]: ", typeid(typeof(s[0])));
      //(s[0]) = 'a'; //Error: s[0] is not mutable
 
      foreach (ref char c; s) {
          writefln("c: ", typeid(typeof(s[0])));
          c = 'a';
          break;
      }
 
      writefln(s);
 
      writefln(typeid(invariant(char[]))); //invariant invariant char[]
      writefln(typeid(invariant(char)[])); //invariant char[]
      invariant(char)[] f;
      writefln(typeid(typeof(f[0]))); //char ????
      //what I expected: invariant(char) like:
      writefln(typeid(invariant(char))); //invariant char
 }
 --------------------------------------------------------------------
 s: const char[]
 s[0]: char
 c: char
 aest
 invariant invariant char[]
 invariant char[]
 char
 invariant char
 
 I can use c (within the foreach) to change elements of the string s.
 Exactly: I can assign single values of type char to each element of the 
 array of invariant chars. (Or I can break after doing so for the n-th 
 element)
 
 But I can't use s[0] to do the same for exactly one element.
 
 The funny thing is: c and s[0] are of the same type ! Both are char.
 
 Lets take a look at string, which is an alias for invariant(char)[].
 What this means: A mutable array of chars (each char can be reassigned, 
 because of the brackets).
 "invariant(char) c;" means: You can assign an other value of type char to c.
 (PS: On the docs it should be mentioned, that invariant(builtintype) / 
 const(builtintype) is useless and behaves like: builtintype)
 not to be confused with "invariant char c;" which means: the value of c 
 will never change and you can't assign an other value to c.
 
 s[0] is of type char, but to make clear, that you can't assign an other 
 char to it, it should be: "invariant char". Then it would be clear, that 
 you can't do: s[0] = 'a';
 
 invariant(char[]) -> invariant invariant char[]
                          |        \--------/  |
                           \------------------/
 
 invariant(char)[] -> invariant char[]
                           \------/
 
 So one element would mean the [] to be removed, and the rest is:
 invariant(char) -> invariant char
 
 But as I pointed out above, this is not the same.
 And that's the reason invariant(char) is always translated to: char
 Because it behaves as if it was a normal char (also said above), if you do:
 invariant(char) c;
 You can assign to it, as if it was just: char c:
 c = 'a';
 
 Now take exactly one element of a string,
 you get an invariant(char) -> char
 But you can't assign an other value of type char to it.
 
 So for arrays it's different, although the type is the same (char).
 
 Daniel
Seems like a bug to me. Here is a simpler example: import std.stdio; void main() { invariant(char)[] s = "test"; foreach (ref char c; s) { c = 'a'; break; } writefln(s); } The output is 'aest' which means that the invariant char array got changed. -- Derek (skype: derek.j.parnell) Melbourne, Australia 6/07/2007 11:56:27 AM
Jul 05 2007