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:
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
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). DanielSeems 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