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

• Daniel919 (65/65) Jul 05 2007 Hi, please look at this code (I discuss the problem below):
• Derek Parnell (17/100) Jul 05 2007 Seems like a bug to me. Here is a simpler example:
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
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