immutable
Hello, I have just recently started programming in D (a very pleasant experience so far I must say), but when experimenting with the the immutable attribute I discovered that the following code does not generate a compile time nor a runtime error: //Decalare immutable string immutable char[] buf = "hello"; //Print the value of buf writefln("buf = %s",buf); //Change buf by using standard input stdin.readln(buf); //Print buf again writefln("buf = %s",buf); This is a bit confusing to be because I had assumed that immutable data really would be immutable (without casting). Why does the code above work? Cheers Nilew
immutable ctors, immutable members, and TDPL
An interesting subject is being debated by some of the heavy hitters of D on the latest beta on the announce NG. However, I have found that there is an inconsistency in TDPL that needs to be addressed. Forgetting the controversy currently brewing, we have the following current situation: struct S { immutable int x; this(int n) { x = n; int y = x; x = 0; } } This compiles, and shows that one can use an immutable, and then the immutable can be changed. This is no good, for obvious reasons. TDPL does not specifically address this issue (from what I can find via manual search), but it does talk about immutable constructors. It's prescription is for immutable constructors to be prohibited from reading any members, and prohibited from calling any functions with 'this' as a parameter. You are allowed to write the members as many times as you want. The idea is if you can't read the data, it can't be inconsistent. Note that this mechanism is not currently implemented in the compiler. I thought "great, let's apply the same technique here". But we have a problem. It would be too restrictive to say you can't call another member function or any other function in a *normal* ctor, just because you declared an immutable member. An immutable member is generally set once and then read from then on. I think both mechanisms (protecting immutable members in the ctor, and protecting all members in an immutable ctor) should be consistent. I think the 'no calling any functions' restriction is to restrictive to apply to normal ctors. My leaning is to re-define how immutable ctors and normal ctors that can initialize immutable members should behave. The immutability should be applied on the first read of the member, or calling a member function/passing 'this' somewhere. Some flow analysis is required for this, but we can be pretty conservative about it. There aren't too many use cases for this stuff anyway. What do you think? -Steve
Call to immutable method during immutable construction
Hi, according to TDPL p. 294 the following call to fun should not be allowed. But it compiles and I see not why that shouldn't be allowed. I think it's a bug in TDPL but I'm unsure. class A { int a; int[] b; this() immutable { a = 5; b = [ 1, 2, 3 ]; fun(); } void fun() immutable { } } Any opinions? Jens
Re: immutable ctors, immutable members, and TDPL
On 05/23/2013 08:41 AM, Steven Schveighoffer wrote: > The immutability should be applied on the first read of the > member, Makes sense to me. Not exactly the same issue but here is a related past discussion: http://forum.dlang.org/thread/khu6tl$q8o$1...@digitalmars.com Quoting deadalnix: "Yes, in general, first assignment in a constructor should be considered as a declaration if the value is not read before. This allow for the mentioned optimization, but many very other important stuff as well, like the construction of immutable objects." And the enhancement request: http://d.puremagic.com/issues/show_bug.cgi?id=9732 Ali
Re: immutable ctors, immutable members, and TDPL
2013/5/24 Ali Çehreli > On 05/23/2013 08:41 AM, Steven Schveighoffer wrote: > > > The immutability should be applied on the first read of the > > member, > > Makes sense to me. > > Not exactly the same issue but here is a related past discussion: > > > http://forum.dlang.org/thread/**khu6tl$q8o$1...@digitalmars.com<http://forum.dlang.org/thread/khu6tl$q8o$1...@digitalmars.com> > > Quoting deadalnix: > > "Yes, in general, first assignment in a constructor should be > considered as a declaration if the value is not read before. > > This allow for the mentioned optimization, but many very other > important stuff as well, like the construction of immutable > objects." > > And the enhancement request: > > > http://d.puremagic.com/issues/**show_bug.cgi?id=9732<http://d.puremagic.com/issues/show_bug.cgi?id=9732> Enh 9732 is a dup of bug 9665? http://d.puremagic.com/issues/show_bug.cgi?id=9665 Kenji Hara
Re: immutable ctors, immutable members, and TDPL
On Thursday, May 23, 2013 11:41:29 Steven Schveighoffer wrote: > An interesting subject is being debated by some of the heavy hitters of D > on the latest beta on the announce NG. > > However, I have found that there is an inconsistency in TDPL that needs to > be addressed. > > What do you think? Sounds sensible to me. I thought that that's how it worked anyway (clearly, I remember wrong - I should probably reread TDPL again one of these days soon, as I sometimes forget little tidbits like this). Sometimes, keeping all of this straight can be quite difficult when you start getting down to the nitty gritty details. - Jonathan M Davis
Re: immutable ctors, immutable members, and TDPL
On Thursday, 23 May 2013 at 15:41:32 UTC, Steven Schveighoffer wrote: ... What do you think? -Steve Honestly, I don't know. It is quite a complex question for me to grasp at once. Only thing I have a string feeling about is that those two cases should be smiliar from the point of type system ("a" type is the same in constructed variables): struct S1 { int a; } struct S2 { immutable int a; } // ... auto s1 = immutable(S1)(); auto s2 = S2();
Re: immutable ctors, immutable members, and TDPL
Also one issue Don has brought my attention to is this snippet: // - immutable int x = 1; void main() { import std.stdio; writeln(x); } static this() { x = 42; } // (does not compile in 2.062 and won't in 2.063) // -- Whatever approach is taken, I think it should be consistent with structs/classes in a sense that global variables are module members and module constructor is, well, constructor. But it looks very hard to do because "immutable" is implicitly "shared". Ideas?
Re: immutable ctors, immutable members, and TDPL
On Friday, 24 May 2013 at 08:47:40 UTC, Dicebot wrote: But it looks very hard to do because "immutable" is implicitly "shared". Ideas? I think that module constructor are pain and suffering. Anyway, this should not work if the ctor isn't shared.
Re: immutable ctors, immutable members, and TDPL
On Friday, 24 May 2013 at 08:47:40 UTC, Dicebot wrote: Also one issue Don has brought my attention to is this snippet: // - immutable int x = 1; void main() { import std.stdio; writeln(x); } static this() { x = 42; } // (does not compile in 2.062 and won't in 2.063) // -- Whatever approach is taken, I think it should be consistent with structs/classes in a sense that global variables are module members and module constructor is, well, constructor. But it looks very hard to do because "immutable" is implicitly "shared". Ideas? That shouldn't compile because the non-shared module constructor writes to the shared variable x whenever a new thread starts with that module. But a better question is whether or not it should compile with a shared module constructor: immutable int x = 1; shared static this() { x = 42; } ... I don't know, but I think it should follow the same logic as with a non-static immutable member variable and a shared default constructor. Also, I think the following shouldn't compile due to a non-shared module constructor assigning to a shared variable (currently it does compile): immutable int x; static this() { import std.random; x = uniform(0, 100); }
Re: immutable ctors, immutable members, and TDPL
On Fri, 24 May 2013 04:47:38 -0400, Dicebot wrote: Also one issue Don has brought my attention to is this snippet: // - immutable int x = 1; void main() { import std.stdio; writeln(x); } static this() { x = 42; } // (does not compile in 2.062 and won't in 2.063) // -- Whatever approach is taken, I think it should be consistent with structs/classes in a sense that global variables are module members and module constructor is, well, constructor. This is not what I am looking to fix. Module ctors are very different from struct ctors. Also, I specifically avoided the "pre-initialized" values, because that is outside the scope of this problem. We assume that for the sake of this argument, the value is uninitialized before the ctor is called. But it looks very hard to do because "immutable" is implicitly "shared". Ideas? Use shared static this, and the runtime should run your module ctors in dependency order. That is, another module that uses x must have this module's ctors run before it. -Steve
Re: immutable ctors, immutable members, and TDPL
On Friday, 24 May 2013 at 13:56:06 UTC, Steven Schveighoffer wrote: Use shared static this, and the runtime should run your module ctors in dependency order. That is, another module that uses x must have this module's ctors run before it. -Steve Oh, awesome! I did not know this. Well, than modules can somewhat mimic struct/class behavior. They are not the same, but they try to look similar in other parts of language (for example, protection attributes) and (in my opinion!) should try the same here.
Re: immutable ctors, immutable members, and TDPL
On Thursday, 23 May 2013 at 15:41:32 UTC, Steven Schveighoffer wrote: An interesting subject is being debated by some of the heavy hitters of D on the latest beta on the announce NG. However, I have found that there is an inconsistency in TDPL that needs to be addressed. Forgetting the controversy currently brewing, we have the following current situation: struct S { immutable int x; this(int n) { x = n; int y = x; x = 0; } } This compiles, and shows that one can use an immutable, and then the immutable can be changed. This is no good, for obvious reasons. I think immutable is something you cannot change. Also, the reverse is true, if you can change something, it's not immutable. According to this logic, x is not immutable inside the scope of the constructor, because you *can* change it. Therefore it should be so that: import std.traits; struct S { immutable int x; this(int n) { static assert(isMutable!(typeof(x))); } } static assert(!isMutable!(typeof(S.init.x)));
Immutable fields
Is it correct for immutable struct fields to act like enum or static const fields? (I don't think so, but I am wrong often): struct Foo { immutable int x = 1; } static assert(Foo.sizeof == 4); void main() {} More info in the D.learn thread: http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D.learn&article_id=22540 Thank you, bearophile
Re: immutable
On Wed, 26 Jan 2011 15:32:58 -0500, Robert wrote: Hello, I have just recently started programming in D (a very pleasant experience so far I must say), but when experimenting with the the immutable attribute I discovered that the following code does not generate a compile time nor a runtime error: //Decalare immutable string immutable char[] buf = "hello"; //Print the value of buf writefln("buf = %s",buf); //Change buf by using standard input stdin.readln(buf); //Print buf again writefln("buf = %s",buf); This is a bit confusing to be because I had assumed that immutable data really would be immutable (without casting). Why does the code above work? It shouldn't. I don't know where the bug is. Please file a bug with a complete program (with a main() function) here: http://d.puremagic.com/issues/enter_bug.cgi BTW, this has a segfault in Linux, so it's definitely trying to overwrite immutable data. -Steve
Re: immutable
BTW, this has a segfault in Linux, so it's definitely trying to overwrite immutable data. Does it also segfault with string buf?
Re: immutable
On Wed, 26 Jan 2011 15:47:23 -0500, Trass3r wrote: BTW, this has a segfault in Linux, so it's definitely trying to overwrite immutable data. Does it also segfault with string buf? No. Now I'm confused :) -Steve
Re: immutable
BTW, this has a segfault in Linux, so it's definitely trying to overwrite immutable data. Does it also segfault with string buf? No. Now I'm confused :) On Linux strings are put into some read-only space. I guess an immutable(char[]) also puts the pointer and length into that storage.
Re: immutable
On 01/26/2011 02:40 PM, Steven Schveighoffer wrote: On Wed, 26 Jan 2011 15:32:58 -0500, Robert wrote: Hello, I have just recently started programming in D (a very pleasant experience so far I must say), but when experimenting with the the immutable attribute I discovered that the following code does not generate a compile time nor a runtime error: //Decalare immutable string immutable char[] buf = "hello"; //Print the value of buf writefln("buf = %s",buf); //Change buf by using standard input stdin.readln(buf); //Print buf again writefln("buf = %s",buf); This is a bit confusing to be because I had assumed that immutable data really would be immutable (without casting). Why does the code above work? It shouldn't. I don't know where the bug is. Please file a bug with a complete program (with a main() function) here: http://d.puremagic.com/issues/enter_bug.cgi BTW, this has a segfault in Linux, so it's definitely trying to overwrite immutable data. -Steve I'd guess this is the problem: void badurk(C,E)(ref C[] x, E y){ x ~= y; } void main(string[] args){ immutable char[] buf = "hello"; static assert(is(typeof(buf) == immutable(char[]))); badurk(buf,'a'); //compiler: la la, this is okay! } OT: this function confuses me: size_t readln(C)(ref C[] buf, dchar terminator = '\n') if (isSomeChar!C) { static if (is(C == char)) { enforce(p && p.handle, "Attempt to read from an unopened file."); return readlnImpl(p.handle, buf, terminator); } else { // TODO: optimize this string s = readln(terminator); if (!s.length) return 0; buf.length = 0; foreach (wchar c; s) <- (?!) { buf ~= c; } return buf.length; } }
Re: immutable
(readln only uses ~= on buf, it doesn't change the original string)
Re: immutable
This is a serious bug. http://d.puremagic.com/issues/show_bug.cgi?id=5492
Re: immutable
"Ellery Newcomer" wrote in message news:ihq1pm$2d2v$1...@digitalmars.com... > > OT: this function confuses me: > > string s = readln(terminator); > foreach (wchar c; s) <- (?!) Automatically converts s from string to wstring and iterates over the wchars. It should be dchar, though, not wchar.
Re: immutable
On Wed, 26 Jan 2011 15:52:25 -0500, Trass3r wrote: (readln only uses ~= on buf, it doesn't change the original string) What? Why does it take a ref argument then? If it doesn't overwrite the buffer passed in, there is no point in giving it a buffer. readln needs a serious redesign it looks like. -Steve
Re: immutable
On Wed, 26 Jan 2011 16:12:58 -0500, Robert wrote: I didn't expect the code to run, hence my question. I tried it on OSX first which might have been the reason. Ran it on Ubuntu too and got the expected segmentation fault. The code shouldn't even compile. But the segfault is OS dependent (as you discovered). Windows also will not segfault. -Steve
Re: immutable
(readln only uses ~= on buf, it doesn't change the original string) What? Why does it take a ref argument then? If it doesn't overwrite the buffer passed in, there is no point in giving it a buffer. No I meant it doesn't alter buf's original content, i.e. "hello" Of course it modifies the array itself via ~= and thus takes it as a ref. Though it should use 'out' instead I think.
Re: immutable
I didn't expect the code to run, hence my question. I tried it on OSX first which might have been the reason. Ran it on Ubuntu too and got the expected segmentation fault. But thank you for the answer, I have filed the bug. Robert
Re: immutable
But thank you for the answer, I have filed the bug. Rats, I've filed one too ;) http://d.puremagic.com/issues/show_bug.cgi?id=5492
Re: immutable
Hopefully they will give it double the attention then ;)
Re: immutable
On Wed, 26 Jan 2011 16:13:41 -0500, Trass3r wrote: (readln only uses ~= on buf, it doesn't change the original string) What? Why does it take a ref argument then? If it doesn't overwrite the buffer passed in, there is no point in giving it a buffer. No I meant it doesn't alter buf's original content, i.e. "hello" Of course it modifies the array itself via ~= and thus takes it as a ref. Though it should use 'out' instead I think. Then why not return the newly-created buffer? Why alter the buffer via a parameter? It makes no sense to me. Better API: char[] readln(); or if you want different char types: C[] readln(C = char)(); I think the original intent was for the code to overwrite the buffer, but it doesn't take into account the append improvements circa 2.041. -Steve
Re: immutable
On 01/26/2011 10:21 PM, Steven Schveighoffer wrote: On Wed, 26 Jan 2011 16:13:41 -0500, Trass3r wrote: (readln only uses ~= on buf, it doesn't change the original string) What? Why does it take a ref argument then? If it doesn't overwrite the buffer passed in, there is no point in giving it a buffer. No I meant it doesn't alter buf's original content, i.e. "hello" Of course it modifies the array itself via ~= and thus takes it as a ref. Though it should use 'out' instead I think. Then why not return the newly-created buffer? Why alter the buffer via a parameter? It makes no sense to me. Better API: char[] readln(); or if you want different char types: C[] readln(C = char)(); Yes, that's how I think readln's API should be. Is a buf version for repeated use? (I guess no, since input comes from a user?) Denis -- _ vita es estrany spir.wikidot.com
Re: immutable
On 1/26/11 6:24 PM, spir wrote: On 01/26/2011 10:21 PM, Steven Schveighoffer wrote: On Wed, 26 Jan 2011 16:13:41 -0500, Trass3r wrote: (readln only uses ~= on buf, it doesn't change the original string) What? Why does it take a ref argument then? If it doesn't overwrite the buffer passed in, there is no point in giving it a buffer. No I meant it doesn't alter buf's original content, i.e. "hello" Of course it modifies the array itself via ~= and thus takes it as a ref. Though it should use 'out' instead I think. Then why not return the newly-created buffer? Why alter the buffer via a parameter? It makes no sense to me. Better API: char[] readln(); or if you want different char types: C[] readln(C = char)(); Yes, that's how I think readln's API should be. Is a buf version for repeated use? (I guess no, since input comes from a user?) Denis There is an overload of readln that looks like that. Andrei
Re: immutable
On Wed, 26 Jan 2011 19:46:43 -0500, Andrei Alexandrescu wrote: On 1/26/11 6:24 PM, spir wrote: On 01/26/2011 10:21 PM, Steven Schveighoffer wrote: On Wed, 26 Jan 2011 16:13:41 -0500, Trass3r wrote: (readln only uses ~= on buf, it doesn't change the original string) What? Why does it take a ref argument then? If it doesn't overwrite the buffer passed in, there is no point in giving it a buffer. No I meant it doesn't alter buf's original content, i.e. "hello" Of course it modifies the array itself via ~= and thus takes it as a ref. Though it should use 'out' instead I think. Then why not return the newly-created buffer? Why alter the buffer via a parameter? It makes no sense to me. Better API: char[] readln(); or if you want different char types: C[] readln(C = char)(); Yes, that's how I think readln's API should be. Is a buf version for repeated use? (I guess no, since input comes from a user?) Denis There is an overload of readln that looks like that. Then is my hypothesis correct that readln is *supposed* to overwrite the buffer? It currently doesn't. -Steve
Re: immutable
Trass3r napisał: > > But thank you for the answer, I have filed the bug. > > Rats, I've filed one too ;) > http://d.puremagic.com/issues/show_bug.cgi?id=5492 We found it over a year ago :) http://d.puremagic.com/issues/show_bug.cgi?id=3534 -- Tomek
immutable range
I got an idea. import std.range; template isImmutableInputRange(R) { enum bool isImmutableInputRange = is(typeof( { R r;// can define a range object if (r.empty) {} // can test for empty auto r2 = r.nextFront(); // can invoke nextFront() auto h = r2.front; // can get the front of the range })); } template isImmutableForwardRange(R) { enum bool isImmutableForwardRange = isImmutableInputRange!R && is(typeof( { R r1; R r2 = r1.save; // can call "save" against a range object })); } template isImmutableBidirectionalRange(R) { enum bool isImmutableBidirectionalRange = isImmutableForwardRange!R && is(typeof(R.init.back()) == typeof(R.init.front())) && is(typeof({ R r; auto r2 = r.nextBack(); })); } void immutableForeach(R, E)(R r, scope void delegate(E) dg) if (isImmutableInputRange!R && is(ElementType!R : E)) { if (r.empty) return; dg(r.front); immutableForeach(r.nextFront(), dg);// tail recursion } void immutableForeachReverse(R, E)(R r, scope void delegate(E) dg) if (isImmutableBidirectionalRange!R && is(ElementType!R : E)) { if (r.empty) return; dg(r.back); immutableForeachReverse(r.nextBack(), dg); // tail recursion } const struct Range { int[] arr; @property int front() const { return arr[0]; } @property bool empty() const { return arr.length > 0; } const(Range) nextFront() const { return Range(arr[1..$]); } const(Range) save() const { return this; } @property int back() const { return arr[$-1]; } const(Range) nextBack() { return Range(arr[0..$-1]); } } static assert(isImmutableInputRange!Range); static assert(isImmutableForwardRange!Range); static assert(isImmutableBidirectionalRange!Range); void main() { const r = Range([1,2,3]); int i = 0; immutableForeach(r, (int v) { assert(v == ++i); }); int j = 3; immutableForeachReverse(r, (int v) { assert(v == j--); }); } Kenji Hara
immutable bug?
I just managed to assign a const(char)[] to a string... caused crashes when the original memory disappeared. inout(char)[] todstr(inout(char)* cstr) pure nothrow { return cstr ? cstr[0 .. std.c.string.strlen(cstr)] : cstr[0 .. 0]; } struct Data { char buffer[256] = void; @property const(char)[] filename() const pure nothrow { return todstr(buffer.ptr); } } struct MyThing { private this(in Data* p) { filename = p.filename; // *** Uh oh! assigned a const(char)[] @property to a string! *** } string filename; } Surely that assignment shouldn't be legal? Shouldn't I need to idup?
Immutable + goto?
import std.stdio; uint bar = 0; void main() { start: immutable uint foo = bar; bar++; writeln(foo); goto start; } foo changes in this case. Is this a real bug, or is it considered undefined behavior to use goto in this way?
Re: Call to immutable method during immutable construction
On Wednesday, November 10, 2010 06:14:07 Jens Mueller wrote: > Hi, > > according to TDPL p. 294 the following call to fun should not be > allowed. But it compiles and I see not why that shouldn't be allowed. I > think it's a bug in TDPL but I'm unsure. > > class A { > int a; > int[] b; > this() immutable { > a = 5; > b = [ 1, 2, 3 ]; > fun(); > } > void fun() immutable { > } > } > > Any opinions? Well, regardless of what the correct behavior is, dmd is not entirely in line with TDPL yet, so there's a good chance that dmd just hasn't been updated to match TDPL yet. Now, I'd have to read the appropriate section of the book again (and I don't have it on me at the moment) to be sure, but IIRC, the reasoning as to why calling fun() was illegal was because all member variables must be initialized in an immutable constructor only once, and they cannot be accessed before they are used, so you'd have to be sure that any other functions which were called didn't access them (including any pre or post-conditions or the invariant), and the compiler is supposed to take the easy and simple route of simply disallowing calls to other member functions in an immutable constructor rather than trying to verify that the functions being called didn't access those variables (particularly since even if the functions being called didn't access any member variables, the functions that _they_ call could, and it could get pretty nasty to verify). Now, it could be that this particular situation is still legal, because the compiler is able to see that you initialized all of the member variables _before_ calling fun(). If it's straightforward enough for the compiler to verify that you never call any member functions prior to initializing all member variables in an immutable constructor (and the compiler may _have_ to be able to be that smart anyway to guarantee that it initializes each member variable exactly once), then I don't see why it shouldn't be legal to call them after all member variables have been initalized, but I don't know if the compiler has to be that smart, and in reality, it's not actually valuable when you think about it. What could fun() actually do which would be useful? You're not returning anything from either it or the constructor, and it's immutable, so it can't alter any state anywhere. It would only make sense for it to be legal if all member variables had already been initialized, but at that point, there's no point to calling any other functions, since they'd have to be immutable and if they're immutable, you can't do anything with them except return a result, and since you're in an immutable constructor, and all member variables are already initialized, you can't do anything useful with that result. So, while I don't necessarily see anything wrong with calling fun() in this situation being legal, I don't see the point. - Jonathan M Davis
Re: Call to immutable method during immutable construction
Jonathan M Davis wrote: > On Wednesday, November 10, 2010 06:14:07 Jens Mueller wrote: > > Hi, > > > > according to TDPL p. 294 the following call to fun should not be > > allowed. But it compiles and I see not why that shouldn't be allowed. I > > think it's a bug in TDPL but I'm unsure. > > > > class A { > > int a; > > int[] b; > > this() immutable { > > a = 5; > > b = [ 1, 2, 3 ]; > > fun(); > > } > > void fun() immutable { > > } > > } > > > > Any opinions? > > Well, regardless of what the correct behavior is, dmd is not entirely in line > with TDPL yet, so there's a good chance that dmd just hasn't been updated to > match TDPL yet. > > Now, I'd have to read the appropriate section of the book again (and I don't > have it on me at the moment) to be sure, but IIRC, the reasoning as to why > calling fun() was illegal was because all member variables must be > initialized > in an immutable constructor only once, and they cannot be accessed before > they > are used, so you'd have to be sure that any other functions which were > called > didn't access them (including any pre or post-conditions or the invariant), > and > the compiler is supposed to take the easy and simple route of simply > disallowing > calls to other member functions in an immutable constructor rather than > trying > to verify that the functions being called didn't access those variables > (particularly since even if the functions being called didn't access any > member > variables, the functions that _they_ call could, and it could get pretty > nasty > to verify). Right. That is why calling fun shouldn't be possible. So you say it's not handled by dmd yet. > Now, it could be that this particular situation is still legal, because the > compiler is able to see that you initialized all of the member variables > _before_ calling fun(). Right. That could also be the case. And my question is what is the case. Is it the simple route that is not implemented at all or is it this more advanced route that is already implemented? I just checked by moving fun() to the beginning. Still works. Further initializing a member in fun() is not allowed. But accessing a member in fun works irrespective when it is called. Actually I find this behavior better than the one defined in TDPL. > If it's straightforward enough for the compiler to verify that you never call > any member functions prior to initializing all member variables in an > immutable > constructor (and the compiler may _have_ to be able to be that smart anyway > to > guarantee that it initializes each member variable exactly once), then I > don't > see why it shouldn't be legal to call them after all member variables have > been > initalized, but I don't know if the compiler has to be that smart, and in > reality, it's not actually valuable when you think about it. What could fun() > actually do which would be useful? You're not returning anything from either > it > or the constructor, and it's immutable, so it can't alter any state anywhere. You mean alter A's state. It could change something outside of A, couldn't it? > It would only make sense for it to be legal if all member variables > had already been initialized, but at that point, there's no point to > calling any other functions, since they'd have to be immutable and if > they're immutable, you can't do anything with them except return a > result, and since you're in an immutable constructor, and all member > variables are already initialized, you can't do anything useful with > that result. See above. > So, while I don't necessarily see anything wrong with calling fun() in this > situation being legal, I don't see the point. My main point is that I'd like to know what is implemented as in mentioned TDPL and what isn't. But I agree with you that calling an immutable member function from the immutable constructor is probably less useful. Jens
Re: Call to immutable method during immutable construction
On Wednesday 10 November 2010 13:01:55 Jens Mueller wrote: > You mean alter A's state. It could change something outside of A, couldn't > it? I suppose that it could. I forgot about that. It's certainly not something that I'd ever think of doing. It would be bizarre to alter global state from a const or immutable function. > > So, while I don't necessarily see anything wrong with calling fun() in > > this situation being legal, I don't see the point. > > My main point is that I'd like to know what is implemented as in > mentioned TDPL and what isn't. I suspect that someone like Don or Walter would have to answer in this case. They're the most likely to know what the compiler is actually doing vs what they intend it to do. A bug report on it should likely be opened though, since it doesn't match TDPL. Either it needs to be fixed to match TDPL (which is likely in this case), or it needs to be made clear what behavior it's supposed to have, at which point the TDPL errata should be updated. - Jonathan M Davis
Re: Call to immutable method during immutable construction
Jonathan M Davis wrote: > On Wednesday 10 November 2010 13:01:55 Jens Mueller wrote: > > > So, while I don't necessarily see anything wrong with calling fun() in > > > this situation being legal, I don't see the point. > > > > My main point is that I'd like to know what is implemented as in > > mentioned TDPL and what isn't. > > I suspect that someone like Don or Walter would have to answer in this case. > They're the most likely to know what the compiler is actually doing vs what > they > intend it to do. A bug report on it should likely be opened though, since it > doesn't match TDPL. Either it needs to be fixed to match TDPL (which is > likely in > this case), or it needs to be made clear what behavior it's supposed to have, > at > which point the TDPL errata should be updated. I added a report. http://d.puremagic.com/issues/show_bug.cgi?id=5200 Thanks for your help. Jens
Re: Immutable fields
"bearophile" wrote in message news:iaqbsb$1d3...@digitalmars.com... > Is it correct for immutable struct fields to act like enum or static const > fields? (I don't think so, but I am wrong often): > immutable struct fields can be changed inside the constructor, so they must be non-static. stuct S { immutable int a; this(int b) { a = b; } }
Re: Immutable fields
On Tuesday 02 November 2010 17:54:35 bearophile wrote: > Is it correct for immutable struct fields to act like enum or static const > fields? (I don't think so, but I am wrong often): > > struct Foo { > immutable int x = 1; > } > static assert(Foo.sizeof == 4); > void main() {} > > > More info in the D.learn thread: > http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D.l > earn&article_id=22540 > > Thank you, > bearophile Assuming that it's the constructor which initializes the variable, then it's going to have to have storage, immutable or not. However, if it's not set by the constructor but directly initialized, then I don't see why the compiler can't treat it as not having storage. At that point, it's conceptually the same as using an enum. Why would it really matter though? If anything, I would have thought that the elimination of the storage would be a good thing, since it reduces the memory footprint of the object. - Jonathan M Davis
Re: Immutable fields
Jonathan M Davis: > Why would it really matter though? I guess you have not followed my link with more explanations, right? :-) Bye, bearophile
Re: Immutable fields
On 03/11/10 00:54, bearophile wrote: Is it correct for immutable struct fields to act like enum or static const fields? (I don't think so, but I am wrong often): struct Foo { immutable int x = 1; } static assert(Foo.sizeof == 4); void main() {} More info in the D.learn thread: http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D.learn&article_id=22540 Thank you, bearophile If it helps, the analogy I always use when explaining immutable is the stone tablet. A running program can chip out a message on a stone tablet (write to immutable memory) but once it's written once it's never going to change again. When your done with a stone tablet all you can do is throw it in the garbage but you can go and chip a new message on a new stone tablet. Don't worry, it took me a while before I realized that an immutable didn't have to be known at compile time as well.
Re: Immutable fields
Daniel Murphy: > immutable struct fields can be changed inside the constructor, so they must > be non-static. So do you think my code shows a compiler bug? Bye, bearophile
Re: Immutable fields
On 03/11/10 02:20, Gareth Charnock wrote: On 03/11/10 00:54, bearophile wrote: Is it correct for immutable struct fields to act like enum or static const fields? (I don't think so, but I am wrong often): struct Foo { immutable int x = 1; } static assert(Foo.sizeof == 4); void main() {} More info in the D.learn thread: http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D.learn&article_id=22540 Thank you, bearophile If it helps, the analogy I always use when explaining immutable is the stone tablet. A running program can chip out a message on a stone tablet (write to immutable memory) but once it's written once it's never going to change again. When your done with a stone tablet all you can do is throw it in the garbage but you can go and chip a new message on a new stone tablet. Don't worry, it took me a while before I realized that an immutable didn't have to be known at compile time as well. Ah, okay, I reread that. You meant is it correct for immutable to act like enum at any time, but I read all the time for some reason. Sorry.
Re: Immutable fields
"bearophile" wrote in message news:iaqgvl$1qb...@digitalmars.com... > So do you think my code shows a compiler bug? I'd like immutable to be implicitly static in some cases eg. void foo() { immutable int[20] table = [...]; } If this is possible, it does reduce the storage required and repeated init times. (Although it seems to be using enum, not static, which has its own set of problems) Removing the storage inside structs completely scews up the memory layout (which is meant to be C compatible) The fact that commenting out the constructor in struct C changes the size of the struct seems like a bug to me, or at least a horribly messy part of the spec. struct A { int x; } struct B { immutable int x; } struct C { immutable int x; this(int a) { x = a; } } Also, this seems to work for me. enum E { A, B }; struct Foo { immutable E x; this(int dummy) { x = E.A; } } struct Bar { immutable E x; this(int dummy) { x = E.B; } } void main() { auto f = Foo(0); assert((cast(Bar*)&f).x == E.A); } Also, What the hell?
Re: Immutable fields
*What the hell? struct Foo { immutable int x = 3; this(int dummy) { auto p = &x; } } void main() { auto f = Foo(0); auto p = &f.x; // Will compile with this commented out }
Re: Immutable fields
On Tuesday 02 November 2010 19:24:29 bearophile wrote: > Jonathan M Davis: > > Why would it really matter though? > > I guess you have not followed my link with more explanations, right? :-) > > Bye, > bearophile I don't really get what you're doing there or what the problem is. You cast one struct to another struct and it retained the same value for x. That seems logical enough. You're just viewing that chunk of memory as a new type. You didn't actually change what's there. My first reaction to seeing that sort of cast though is that it's a bad idea anyway, though I guess that whether an immutable variable has storage could affect the result in such a case. Generally though, I would have argued that if you weren't going to set the variable with the constructor, it should probably be an enum anyway. - Jonathan M Davis
Re: Immutable fields
Jonathan M Davis, el 2 de noviembre a las 20:02 me escribiste: > On Tuesday 02 November 2010 19:24:29 bearophile wrote: > > Jonathan M Davis: > > > Why would it really matter though? > > > > I guess you have not followed my link with more explanations, right? :-) > > > > Bye, > > bearophile > > I don't really get what you're doing there or what the problem is. You cast > one > struct to another struct and it retained the same value for x. That seems > logical enough. You're just viewing that chunk of memory as a new type. You > didn't actually change what's there. My first reaction to seeing that sort of > cast though is that it's a bad idea anyway, though I guess that whether an > immutable variable has storage could affect the result in such a case. > Generally > though, I would have argued that if you weren't going to set the variable > with > the constructor, it should probably be an enum anyway. I don't think it's a good idea to optimize out a struct member, as structs are often used to represent memory layouts when interacting with low level stuff (or not so low-level, like reading and writing a packet from the network). It seems pretty silly to have to avoid using immutable in those cases just to let the compiler "please, don't remove store from this struct". -- Leandro Lucarella (AKA luca) http://llucax.com.ar/ -- GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145 104C 949E BFB6 5F5A 8D05) -- Y2K - what a disappointment... i had at least expected one nuclear plant to blow
Re: Immutable fields
Daniel Murphy, el 3 de noviembre a las 13:52 me escribiste: > "bearophile" wrote in message > news:iaqgvl$1qb...@digitalmars.com... > > So do you think my code shows a compiler bug? > > I'd like immutable to be implicitly static in some cases eg. > > void foo() > { > immutable int[20] table = [...]; > } I think immutable should NEVER, EVER be optimized-out from a struct, for the reasons I gave in the other post. I really hope this IS a bug, if D would like to stay being a system programming language. Struct are extremely important to represent memory layouts, and making that incompatible with immutable seems extremely silly. -- Leandro Lucarella (AKA luca) http://llucax.com.ar/ -- GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145 104C 949E BFB6 5F5A 8D05) -- El techo de mi cuarto lleno de galaxias
Re: Immutable fields
On Tuesday 02 November 2010 21:00:00 Leandro Lucarella wrote: > Jonathan M Davis, el 2 de noviembre a las 20:02 me escribiste: > > On Tuesday 02 November 2010 19:24:29 bearophile wrote: > > > Jonathan M Davis: > > > > Why would it really matter though? > > > > > > I guess you have not followed my link with more explanations, right? > > > :-) > > > > > > Bye, > > > bearophile > > > > I don't really get what you're doing there or what the problem is. You > > cast one struct to another struct and it retained the same value for x. > > That seems logical enough. You're just viewing that chunk of memory as a > > new type. You didn't actually change what's there. My first reaction to > > seeing that sort of cast though is that it's a bad idea anyway, though I > > guess that whether an immutable variable has storage could affect the > > result in such a case. Generally though, I would have argued that if you > > weren't going to set the variable with the constructor, it should > > probably be an enum anyway. Perhaps, but is it reasonable to be worrying about memory layouts like that when you're dealing with immutable? I would have thought that in cases where memory layouts like that mattered, you wouldn't be using immutable, since you're probably interfacing with C code or somesuch. It may be that we ultimately don't want to make immutable be optimized away (since you can just use an enum instead if you do want it to be optimized away), but it doesn't surprise me at all if the decision was made to optimize immutables away, since at first glance, at least, it seems like a good optimization and that there's no real need to keep it around if you can optimize it out. - Jonathan M Davis
Re: Immutable fields
On Tue, 02 Nov 2010 20:54:35 -0400, bearophile wrote: > Is it correct for immutable struct fields to act like enum or static > const fields? (I don't think so, but I am wrong often): This is bug 3449: http://d.puremagic.com/issues/show_bug.cgi?id=3449 -Lars
Re: Immutable fields
Lars T. Kyllingstad: > This is bug 3449: > > http://d.puremagic.com/issues/show_bug.cgi?id=3449 Thank you to you and the others that have answered in this thread. That's an important bug, it changes how much I can use immutables. Bye, bearophile
Re: Immutable fields
On 03/11/2010 03:06, Daniel Murphy wrote: "bearophile" wrote in message news:iaqbsb$1d3...@digitalmars.com... Is it correct for immutable struct fields to act like enum or static const fields? (I don't think so, but I am wrong often): immutable struct fields can be changed inside the constructor, so they must be non-static. Const/immutable struct members are an ugly mess, and a big hole in the const system. http://d.puremagic.com/issues/show_bug.cgi?id=2625 Stewart.
Re: Immutable fields
On 11/7/10 2:40 PM, Stewart Gordon wrote: On 03/11/2010 03:06, Daniel Murphy wrote: "bearophile" wrote in message news:iaqbsb$1d3...@digitalmars.com... Is it correct for immutable struct fields to act like enum or static const fields? (I don't think so, but I am wrong often): immutable struct fields can be changed inside the constructor, so they must be non-static. Const/immutable struct members are an ugly mess, and a big hole in the const system. http://d.puremagic.com/issues/show_bug.cgi?id=2625 Stewart. There are problems with the implementation, not the design. Fixing const and immutable will be #1 priority once the 64-bit dmd is off the gates. Andrei
Re: Immutable fields
On Sunday 07 November 2010 17:13:51 Andrei Alexandrescu wrote: > There are problems with the implementation, not the design. Fixing const > and immutable will be #1 priority once the 64-bit dmd is off the gates. Now, _that_ is good news. The problems with const and immutable have long been some of the most annoying. - Jonathan M Davis
Re: Immutable fields
On 2010-11-08 02:13, Andrei Alexandrescu wrote: On 11/7/10 2:40 PM, Stewart Gordon wrote: On 03/11/2010 03:06, Daniel Murphy wrote: "bearophile" wrote in message news:iaqbsb$1d3...@digitalmars.com... Is it correct for immutable struct fields to act like enum or static const fields? (I don't think so, but I am wrong often): immutable struct fields can be changed inside the constructor, so they must be non-static. Const/immutable struct members are an ugly mess, and a big hole in the const system. http://d.puremagic.com/issues/show_bug.cgi?id=2625 Stewart. There are problems with the implementation, not the design. Fixing const and immutable will be #1 priority once the 64-bit dmd is off the gates. Andrei Why can't we get an official roadmap for this? I thought dynamic libraries was next after 64bit. -- /Jacob Carlborg
Re: Immutable fields
On 03/11/2010 10:42, Lars T. Kyllingstad wrote: On Tue, 02 Nov 2010 20:54:35 -0400, bearophile wrote: Is it correct for immutable struct fields to act like enum or static const fields? (I don't think so, but I am wrong often): This is bug 3449: http://d.puremagic.com/issues/show_bug.cgi?id=3449 -Lars Ouch, this is a very nasty bug indeed. :S -- Bruno Medeiros - Software Engineer
Immutable nested functions
A while ago I pointed out that the result of an immutably pure function (all arguments immutable, doesn't mutate globals) can be safely converted to immutable. More here: http://d.puremagic.com/issues/show_bug.cgi?id=5081 It helps with building complex immutable structures. Problem is, virtually every construction site is different so one is forced to define a new initializer function every time. To illustrate: void main() { immutable Node* init_leaf = ... ; uint breadth = ... ; immutable Node* tree = grow_tree(init_leaf, breadth); } Node* grow_tree(immutable Node* init_leaf, uint breadth) pure { Node* root = new Node; foreach (0..breadth) { Node* leaf = new Node(init_leaf); leaf.parent = root; root.leaves ~= leaf; } return root; } I tried to find a way to create ad-hoc functions conveniently. Naturally, I turned to nested functions: void main() { immutable Node* init_leaf = ... ; uint breadth = ... ; Node* grow_tree() pure immutable { Node* root = new Node; foreach (0..breadth) { Node* leaf = new Node(init_leaf); leaf.parent = root; root.leaves ~= leaf; } return root; } immutable Node* tree = grow_tree(); } Nested functions to be immutably pure must also guarantee that nothing gets mutated through its stack frame pointer. But there's a problem -- the compiler won't accept 'immutable' on a nested function. I think it should -- just like an immutable member function (e.g. in a class) is allowed to play only with immutable members of that class, an immutable nested function should be allowed to play only with the immutable members of the stack frame. It may seem a lesser change but I'm pretty excited as it solves the long-standing problems with immutable structure initialization. Excitement aside, I got questions: 1. I'm proposing to proliferate the concept of immutability from 'this' reference to a stack frame pointer. Although I'm confident it makes sense as these are interchangeable in delegates, I could use some criticism to either reject or strengthen the idea. 2. What about delegates? Should there be means to express a "delegate that doesn't mutate through its 'this'/stack frame pointer"? What should the syntax be for defining such delegate type and for lambdas (delegate literals)? 3. (vaguely related) Should there be means to express annotated delegates in general (e.g. pure, nothrow). What about annotated lambdas? -- Tomek
CTFE, std.move & immutable
I was looking to find a way to make std.algorithm.move CTFE-able. AFAIK it's not easy as it explicitly reinterprets data as chunk of bytes and that's something CTFE doesn't support at all. So I went on and tried to just make a copy and then put write T.init into source, that's a copy and is somewhat fragile w.r.t. opAssign but should work. And then... std\algorithm.d(1563): Error: cannot modify struct source Data with immutable members std\container.d(983): Error: template instance std.algorithm.move!(Data) error instantiating std\container.d(1490):instantiated from here: SList!(Data) std\container.d(1490): Error: template instance std.container.SList!(Data) error instantiating Strangely it moves a struct with a const field. In essence it can move immutable struct and will happily bit-blast it's previous location with T.init. That could be quite problematic... Just for fun I tried this, kind shocked (and hit another bug in the compiler while writing it): import std.algorithm; struct C{ int dummy; } struct S{ immutable C c; int dummy; this(int x){ c = C(x); dummy = x; } //to get T.init memcpy-ed over us this(this){} //uncomment this to the impenetrable: // Error: can only initialize const member c inside constructor // And no line number ... // ~this(){} //curiously having ~this() without this(this) works but not together } immutable C a = C(36); S s = S(47); void main(){ //auto x = move(a); //doesn't compile, pointer to immutable vs void* in memcpy //assert(a.dummy == 0); // auto y = move(s); assert(s.c.dummy == 0); //yay! we've fooled typesystem assert(y.c.dummy == 47); } Soo... CTFE won't allow us to grossly break typesystem with an interpret cast. I believe we should forbid moving immutable/const stuff and honor the typesystem. In any case for message passing (the prime use case) you still can move pointer to (slice of) immutable anyway? P.S. I'm not first to discover this odd behavior of move... A related pull request mentioning this problem among others: https://github.com/D-Programming-Language/phobos/pull/923 -- Dmitry Olshansky
Re: immutable range
On Sun, 16 Oct 2011 07:37:03 -0400, kenji hara wrote: I got an idea. import std.range; template isImmutableInputRange(R) { enum bool isImmutableInputRange = is(typeof( { R r;// can define a range object if (r.empty) {} // can test for empty auto r2 = r.nextFront(); // can invoke nextFront() auto h = r2.front; // can get the front of the range })); } template isImmutableForwardRange(R) { enum bool isImmutableForwardRange = isImmutableInputRange!R && is(typeof( { R r1; R r2 = r1.save; // can call "save" against a range object })); } template isImmutableBidirectionalRange(R) { enum bool isImmutableBidirectionalRange = isImmutableForwardRange!R && is(typeof(R.init.back()) == typeof(R.init.front())) && is(typeof({ R r; auto r2 = r.nextBack(); })); } void immutableForeach(R, E)(R r, scope void delegate(E) dg) if (isImmutableInputRange!R && is(ElementType!R : E)) { if (r.empty) return; dg(r.front); immutableForeach(r.nextFront(), dg);// tail recursion } void immutableForeachReverse(R, E)(R r, scope void delegate(E) dg) if (isImmutableBidirectionalRange!R && is(ElementType!R : E)) { if (r.empty) return; dg(r.back); immutableForeachReverse(r.nextBack(), dg); // tail recursion } const struct Range { int[] arr; @property int front() const { return arr[0]; } @property bool empty() const { return arr.length > 0; } const(Range) nextFront() const { return Range(arr[1..$]); } const(Range) save() const { return this; } @property int back() const { return arr[$-1]; } const(Range) nextBack() { return Range(arr[0..$-1]); } } static assert(isImmutableInputRange!Range); static assert(isImmutableForwardRange!Range); static assert(isImmutableBidirectionalRange!Range); void main() { const r = Range([1,2,3]); int i = 0; immutableForeach(r, (int v) { assert(v == ++i); }); int j = 3; immutableForeachReverse(r, (int v) { assert(v == j--); }); } Kenji Hara I don't think this scales well. Not only are you introducing a new type of range, you are introducing a new *class* of range. One which does not work with any existing algorithms. The solution must be compatible with all the existing range functions (which do not modify data), or it doesn't work. -Steve
Immutable Message Passing
This should work, right? I'm not just going crazy or something? import std.concurrency; import std.stdio; class Bob { } void main() { auto tid = spawn(&b); tid.send(new immutable(Bob)()); } void b() { receive( (immutable(Bob) b) { writeln("got it"); } ); } I'm getting this from both GDC (trunk) and DMD (2.056 and trunk - I can't seem to get 2.055 to run): core.exception.AssertError@/usr/include/d/std/variant.d(286): immutable(Bob) Seems like some type conversion isn't working properly and variant is flagging immutable types as not assignable?
Immutable static arrays
Is this a bug? import std.stdio; void main() { immutable(int)[4] a; immutable(int[4]) b; writeln(typeid(a)); writeln(typeid(b)); } Output: immutable(int[4]) immutable(int[4]) So there's no tail-const type for static arrays? More to the point, how should AA's with immutable static array keys be implemented? The current implementation doesn't work at all because the input static array can't be assigned to the Slot (the static array field in Slot is completely immutable, even from the Slot ctor???). T -- It is widely believed that reinventing the wheel is a waste of time; but I disagree: without wheel reinventers, we would be still be stuck with wooden horse-cart wheels.
immutable and std.parallelism.Task
I'm pretty sure this is a bug, but the error makes me think I'm somehow using immutable incorrectly: import std.parallelism; class Test { } void doSomething(immutable(Test) test) { } void main() { immutable(Test) test = new immutable(Test)(); taskPool().put(task!(doSomething)(test)); } compiler output: Error: can only initialize const member __args_field_0 inside constructor Error: this is not mutable /usr/include/d2/4.6.0/std/parallelism.d:734: Error: template instance std.parallelism.Task!(doSomething,immutable(Test)) error instantiating tasktest.d:11:instantiated from here: task!(doSomething,immutable(Test))
optimized immutable containers
Is anyone aware of the new immutable containers in .Net framework? http://blogs.msdn.com/b/bclteam/archive/2012/12/18/preview-of-immutable-collections-released-on-nuget.aspx. While we can attach the immutable qualifier to any D containers, they will not perform nearly as well because they are essentially mutable structures. Making them immutable doesn't change the way they work, it merely forbids us to call the modifying methods. Every time we need to modify them we have to copy the entire thing which is not very efficient. The .Net immutable containers are specially optimized so that they share the underlying data as much as possible. Creating a modified copy is cheap, usually O(1) or O(logN). I think having something similar in D would make immutables much more attractive.
immutable and RC
Is it possible to write a wrapper for file handles, that is immutable if we don't plan to swap out the handle and the ref count is in some external data structure and only accessed in ctors/dtors of the struct ? It would look quite a bit like some sort of head immutable, but with no access to the mutable parts. The motivation is that immutable is inherently shared, so it simplifies code where a file handle might be used by several threads but synchronization is ensured by the operating system or at a higher level in our code. (Otherwise one would have to reimplement read, write, handle, ... with the exact same code, but `shared` attached or cast away `shared`, which is wrong.) -- Marco
Re: immutable bug?
On Saturday, 11 January 2014 at 18:29:36 UTC, Manu wrote: I just managed to assign a const(char)[] to a string... caused crashes when the original memory disappeared. inout(char)[] todstr(inout(char)* cstr) pure nothrow { return cstr ? cstr[0 .. std.c.string.strlen(cstr)] : cstr[0 .. 0]; } struct Data { char buffer[256] = void; @property const(char)[] filename() const pure nothrow { return todstr(buffer.ptr); } } struct MyThing { private this(in Data* p) { filename = p.filename; // *** Uh oh! assigned a const(char)[] @property to a string! *** } string filename; } Surely that assignment shouldn't be legal? Shouldn't I need to idup? I don't know about the details of what is/isn't legal here, but the only reason the compiler accepts it is because filename is marked as pure.
Re: immutable bug?
On Saturday, 11 January 2014 at 18:43:39 UTC, John Colvin wrote: I don't know about the details of what is/isn't legal here, but the only reason the compiler accepts it is because filename is marked as pure. It is legal exactly because function is marked as pure. Result of pure function is implicitly convertible to immutable.
Re: immutable bug?
On Saturday, 11 January 2014 at 18:48:15 UTC, Maxim Fomin wrote: It is legal exactly because function is marked as pure. Result of pure function is implicitly convertible to immutable. It shouldn't be here though... the reason it is implicitly convertable is that pure means the result is unique. But, with the hidden this pointer having a reference to the data as well, it obviously is not unique. I think the compiler should catch this; i'd call it a bug.
Re: immutable bug?
On Saturday, 11 January 2014 at 18:48:15 UTC, Maxim Fomin wrote: On Saturday, 11 January 2014 at 18:43:39 UTC, John Colvin wrote: I don't know about the details of what is/isn't legal here, but the only reason the compiler accepts it is because filename is marked as pure. It is legal exactly because function is marked as pure. Result of pure function is implicitly convertible to immutable. I had heard this mentioned before; is it true in all cases? Even when the function returns a reference to external data?
Re: immutable bug?
On Saturday, 11 January 2014 at 18:29:36 UTC, Manu wrote: I just managed to assign a const(char)[] to a string... caused crashes when the original memory disappeared. inout(char)[] todstr(inout(char)* cstr) pure nothrow { return cstr ? cstr[0 .. std.c.string.strlen(cstr)] : cstr[0 .. 0]; } struct Data { char buffer[256] = void; @property const(char)[] filename() const pure nothrow { return todstr(buffer.ptr); } } struct MyThing { private this(in Data* p) { filename = p.filename; // *** Uh oh! assigned a const(char)[] @property to a string! *** } string filename; } Surely that assignment shouldn't be legal? Shouldn't I need to idup? Simplified: const(char)[] slice(ref const char[1] c) pure nothrow { return c[]; } void main() { char[1] m = "."; immutable i = slice(m); // should not compile assert(i == "."); m = "!"; // uh-oh assert(i == "."); // fails }
Re: immutable bug?
On Saturday, 11 January 2014 at 18:52:39 UTC, Adam D. Ruppe wrote: On Saturday, 11 January 2014 at 18:48:15 UTC, Maxim Fomin wrote: It is legal exactly because function is marked as pure. Result of pure function is implicitly convertible to immutable. It shouldn't be here though... the reason it is implicitly convertable is that pure means the result is unique. But, with the hidden this pointer having a reference to the data as well, it obviously is not unique. I think the compiler should catch this; i'd call it a bug. Creating undefined behavior is not a sufficient reason to be a bug. Changelog mentions example with pure struct constructors which provide value implicitly castable to immutable. So, strictly speaking current behavior is conforming to spec. You can still argue that the example does not address the issue with 'this' parameter, so code should be rejected (which should happen from safity aspect). I think this case was not considered when 'unique expression' was introduced, so it is yet another hole in type system (to be more precise, bug is in spec-language, not compiler).
Re: immutable bug?
On 01/11/2014 08:16 PM, Maxim Fomin wrote: On Saturday, 11 January 2014 at 18:52:39 UTC, Adam D. Ruppe wrote: On Saturday, 11 January 2014 at 18:48:15 UTC, Maxim Fomin wrote: It is legal exactly because function is marked as pure. Result of pure function is implicitly convertible to immutable. It shouldn't be here though... the reason it is implicitly convertable is that pure means the result is unique. But, with the hidden this pointer having a reference to the data as well, it obviously is not unique. I think the compiler should catch this; i'd call it a bug. Creating undefined behavior is not a sufficient reason to be a bug. ... Add a @safe annotation and it is. Changelog mentions example with pure struct constructors which provide value implicitly castable to immutable. So, strictly speaking current behavior is conforming to spec. You can still argue that the example does not address the issue with 'this' parameter, so code should be rejected (which should happen from safity aspect). I think this case was not considered when 'unique expression' was introduced, so it is yet another hole in type system (to be more precise, bug is in spec-language, not compiler). It is an implementation bug. Implicit conversion to immutable is only supposed to work for strongly pure functions.
Re: immutable bug?
On Saturday, 11 January 2014 at 21:16:55 UTC, Timon Gehr wrote: It is an implementation bug. Implicit conversion to immutable is only supposed to work for strongly pure functions. Can someone that knows all the details of the purity strength semantic differences please open a PR to get some documentation in the spec? I've updated this bug with a comment: https://d.puremagic.com/issues/show_bug.cgi?id=7456
Re: immutable bug?
On 12 January 2014 04:52, Adam D. Ruppe wrote: > On Saturday, 11 January 2014 at 18:48:15 UTC, Maxim Fomin wrote: > >> It is legal exactly because function is marked as pure. Result of pure >> function is implicitly convertible to immutable. >> > > It shouldn't be here though... the reason it is implicitly convertable is > that pure means the result is unique. Can you explain how this is true? I can't see anything about the concept of purity that suggests the result should be unique... Pure just means given the same inputs, it will produce the same outputs; external state can't affect the calculation. In this case, that's perfectly true. 'this' is just a function arg; it's not mutated by external state (or at all), given the same this, it will return the same thing every time. That doesn't make any claims about what 'this' is though, and whether it's immutable or 'unique' or whatever. It just promises to transform it in an identical way given the same inputs... ? But, with the hidden this pointer having a reference to the data as well, > it obviously is not unique. I think the compiler should catch this; i'd > call it a bug. >
Re: immutable bug?
On Sunday, 12 January 2014 at 00:50:30 UTC, Manu wrote: On 12 January 2014 04:52, Adam D. Ruppe It shouldn't be here though... the reason it is implicitly convertable is that pure means the result is unique. Can you explain how this is true? I touched on the topic in a short section of my old purity article: http://klickverbot.at/blog/2012/05/purity-in-d/#_and___again David
Re: immutable bug?
On Sunday, 12 January 2014 at 00:50:30 UTC, Manu wrote: On 12 January 2014 04:52, Adam D. Ruppe wrote: On Saturday, 11 January 2014 at 18:48:15 UTC, Maxim Fomin wrote: It is legal exactly because function is marked as pure. Result of pure function is implicitly convertible to immutable. It shouldn't be here though... the reason it is implicitly convertable is that pure means the result is unique. Can you explain how this is true? I can't see anything about the concept of purity that suggests the result should be unique... Pure just means given the same inputs, it will produce the same outputs; external state can't affect the calculation. How could the result not be unique, or at least immutable? Pure functions cannot read mutable global state, so any global state returned must be immutable. Strong pure functions can also only have immutable arguments, so anything returned from those will be immutable. The only other thing that can be returned must be created within the function, which will be unique, and safely converted to immutable.
Re: immutable bug?
On 12 January 2014 11:05, Peter Alexander wrote: > On Sunday, 12 January 2014 at 00:50:30 UTC, Manu wrote: > >> On 12 January 2014 04:52, Adam D. Ruppe >> wrote: >> >> On Saturday, 11 January 2014 at 18:48:15 UTC, Maxim Fomin wrote: >>> >>> It is legal exactly because function is marked as pure. Result of pure >>>> function is implicitly convertible to immutable. >>>> >>>> >>> It shouldn't be here though... the reason it is implicitly convertable is >>> that pure means the result is unique. >>> >> >> >> Can you explain how this is true? I can't see anything about the concept >> of >> purity that suggests the result should be unique... >> Pure just means given the same inputs, it will produce the same outputs; >> external state can't affect the calculation. >> > > How could the result not be unique, or at least immutable? Pure functions > cannot read mutable global state, so any global state returned must be > immutable. Strong pure functions can also only have immutable arguments, so > anything returned from those will be immutable. The only other thing that > can be returned must be created within the function, which will be unique, > and safely converted to immutable. > But pure functions can (and do) return their arguments, and it's obviously not a 'strongly pure' function. So I just can't see how the assertion that it should be unique stands? Also, I was under the impression a 'strongly pure' function's arguments only need to be const, not necessarily immutable. Purity says something about the transformation performed by the function, nothing about the data it operates on. Why should all arguments need to be immutable?
Re: immutable bug?
On Sunday, 12 January 2014 at 02:11:18 UTC, Manu wrote: But pure functions can (and do) return their arguments, and it's obviously not a 'strongly pure' function. So I just can't see how the assertion that it should be unique stands? That's the bug. Your function isn't strongly pure, so the result shouldn't be convertible to immutable and isn't necessarily unique. Only strongly pure functions can have results convertible to immutable. Also, I was under the impression a 'strongly pure' function's arguments only need to be const, not necessarily immutable. Purity says something about the transformation performed by the function, nothing about the data it operates on. Why should all arguments need to be immutable? You don't need immutable arguments for purity, just strong purity. It's a stronger guarantee, more than normally guaranteed. Think of strong purity as pure + referentially transparent. Sorry, yes you're right, they only need to be const. And it is only if you return a mutable value that the result becomes convertible to immutable. int* f(const(int)* x); // convertible const(int)* f(const(int)* x); // not-convertible This is safe in the first instance because the result could not have come from x due to x being const. In the second instance, the result could have come from x, so it cannot be implicitly converted to immutable.
Re: immutable bug?
On Sunday, 12 January 2014 at 02:11:18 UTC, Manu wrote: Also, I was under the impression a 'strongly pure' function's arguments only need to be const, not necessarily immutable. Purity says something about the transformation performed by the function, nothing about the data it operates on. Why should all arguments need to be immutable? Your definition of purity states it clearly that the purity depends on the mutability of the input data.
Re: immutable bug?
On 1/12/14 2:49 AM, Peter Alexander wrote: On Sunday, 12 January 2014 at 02:11:18 UTC, Manu wrote: But pure functions can (and do) return their arguments, and it's obviously not a 'strongly pure' function. So I just can't see how the assertion that it should be unique stands? That's the bug. Your function isn't strongly pure, so the result shouldn't be convertible to immutable and isn't necessarily unique. Only strongly pure functions can have results convertible to immutable. Yep. Has this been placed in bugzilla? It's rather hi-pri. Andrei
Re: immutable bug?
"Andrei Alexandrescu" wrote in message news:laugbo$2jcq$3...@digitalmars.com... Yep. Has this been placed in bugzilla? It's rather hi-pri. If this isn't https://d.puremagic.com/issues/show_bug.cgi?id=11503 - it most likely has the same cause.
Re: immutable bug?
On 13 January 2014 02:37, Andrei Alexandrescu wrote: > On 1/12/14 2:49 AM, Peter Alexander wrote: > >> On Sunday, 12 January 2014 at 02:11:18 UTC, Manu wrote: >> >>> But pure functions can (and do) return their arguments, and it's >>> obviously >>> not a 'strongly pure' function. So I just can't see how the assertion >>> that >>> it should be unique stands? >>> >> >> That's the bug. Your function isn't strongly pure, so the result >> shouldn't be convertible to immutable and isn't necessarily unique. Only >> strongly pure functions can have results convertible to immutable. >> > > Yep. Has this been placed in bugzilla? It's rather hi-pri. I wasn't sure if it was definitely a bug. Certainly seemed like one though. https://d.puremagic.com/issues/show_bug.cgi?id=11908
Re: immutable bug?
On 1/12/14 8:46 AM, Daniel Murphy wrote: "Andrei Alexandrescu" wrote in message news:laugbo$2jcq$3...@digitalmars.com... Yep. Has this been placed in bugzilla? It's rather hi-pri. If this isn't https://d.puremagic.com/issues/show_bug.cgi?id=11503 - it most likely has the same cause. Put $150 on this. https://www.bountysource.com/issues/1325974-type-system-breaking-caused-by-implicit-conversion-for-the-value-returned-from-pure-function Andrei
Re: immutable bug?
On 01/12/2014 11:49 AM, Peter Alexander wrote: Also, I was under the impression a 'strongly pure' function's arguments only need to be const, not necessarily immutable. Purity says something about the transformation performed by the function, nothing about the data it operates on. Why should all arguments need to be immutable? You don't need immutable arguments for purity, just strong purity. It's a stronger guarantee, more than normally guaranteed. Think of strong purity as pure + referentially transparent. Sorry, yes you're right, they only need to be const. And it is only if you return a mutable value that the result becomes convertible to immutable. int* f(const(int)* x); // convertible const(int)* f(const(int)* x); // not-convertible ... (I assume you meant those to be pure.) This is safe in the first instance because the result could not have come from x due to x being const. In the second instance, the result could have come from x, so it cannot be implicitly converted to immutable. Well, currently things are supposed to be as follows: 1. A strongly pure callable is a pure callable whose parameter types implicitly convert to immutable. 2. The result of a call to a strongly pure callable implicitly converts to immutable. The following vastly more general rule would still be sound and also capture your case: - The result of a call to a pure callable, where all arguments whose corresponding parameter types are incompatible with the result type implicitly convert to immutable (shared), implicitly converts to immutable (shared). (Incompatibility should probably just be incompatibility of qualifiers.)
Re: immutable bug?
On Sunday, 12 January 2014 at 18:09:59 UTC, Andrei Alexandrescu wrote: Put $150 on this. https://www.bountysource.com/issues/1325974-type-system-breaking-caused-by-implicit-conversion-for-the-value-returned-from-pure-function I posted a fix for this issue (i.e. the one on which the bounty was set). Now tackling Manu's example, which turns out to exhibit a slightly different bug. David
Re: immutable bug?
On 01/12/2014 07:10 PM, Andrei Alexandrescu wrote: On 1/12/14 8:46 AM, Daniel Murphy wrote: "Andrei Alexandrescu" wrote in message news:laugbo$2jcq$3...@digitalmars.com... Yep. Has this been placed in bugzilla? It's rather hi-pri. If this isn't https://d.puremagic.com/issues/show_bug.cgi?id=11503 - it most likely has the same cause. Put $150 on this. https://www.bountysource.com/issues/1325974-type-system-breaking-caused-by-implicit-conversion-for-the-value-returned-from-pure-function Andrei This issue was trivial, and yet was assigned a higher bounty than e.g. fixing CTFE performance, which requires a large investment as far as I understand. This raises the question of how bountied issues are selected. There are other serious problems with the type system implementation, eg: https://d.puremagic.com/issues/show_bug.cgi?id=9149 https://d.puremagic.com/issues/show_bug.cgi?id=10376 https://d.puremagic.com/issues/show_bug.cgi?id=9148 On a related note, I think it makes no sense to put a bounty on the "Object not const-correct" issue. What would someone be required to do in order to get the bounty for that issue?
Re: immutable bug?
On Saturday, 11 January 2014 at 18:29:36 UTC, Manu wrote: ... I'm just a bit confused, but recently I've seen many topics from Manu and problems which he's facing with D. So my question is: You don't had any problems when coding "Remedy's" 3D engine integration with D back then? (http://dconf.org/2013/talks/evans_1.html) or am I missing something?
Re: immutable bug?
On 01/12/2014 10:06 PM, Johnny Walking wrote: On Saturday, 11 January 2014 at 18:29:36 UTC, Manu wrote: ... I'm just a bit confused, but recently I've seen many topics from Manu and problems which he's facing with D. So my question is: You don't had any problems when coding "Remedy's" 3D engine integration with D back then? (http://dconf.org/2013/talks/evans_1.html) or am I missing something? http://en.wikipedia.org/wiki/Baader-Meinhof_phenomenon
Re: immutable bug?
On 1/12/14 12:35 PM, Timon Gehr wrote: On 01/12/2014 07:10 PM, Andrei Alexandrescu wrote: On 1/12/14 8:46 AM, Daniel Murphy wrote: "Andrei Alexandrescu" wrote in message news:laugbo$2jcq$3...@digitalmars.com... Yep. Has this been placed in bugzilla? It's rather hi-pri. If this isn't https://d.puremagic.com/issues/show_bug.cgi?id=11503 - it most likely has the same cause. Put $150 on this. https://www.bountysource.com/issues/1325974-type-system-breaking-caused-by-implicit-conversion-for-the-value-returned-from-pure-function Andrei This issue was trivial, and yet was assigned a higher bounty than e.g. fixing CTFE performance, which requires a large investment as far as I understand. This raises the question of how bountied issues are selected. I select them with a focus on impact. Clearly the process could be improved. There are other serious problems with the type system implementation, eg: https://d.puremagic.com/issues/show_bug.cgi?id=9149 https://d.puremagic.com/issues/show_bug.cgi?id=10376 https://d.puremagic.com/issues/show_bug.cgi?id=9148 Thanks, will take those under advisement. FWIW there's been a thread taking suggestions. On a related note, I think it makes no sense to put a bounty on the "Object not const-correct" issue. What would someone be required to do in order to get the bounty for that issue? Make sure we have a complete solution for invoking Object's methods against const and immutable Objects? Andrei
Re: immutable bug?
On 01/12/2014 11:51 PM, Andrei Alexandrescu wrote: ... Put $150 on this. https://www.bountysource.com/issues/1325974-type-system-breaking-caused-by-implicit-conversion-for-the-value-returned-from-pure-function Andrei This issue was trivial, and yet was assigned a higher bounty than e.g. fixing CTFE performance, which requires a large investment as far as I understand. This raises the question of how bountied issues are selected. I select them with a focus on impact. Clearly the process could be improved. ... I see. FWIW it _did_ get an issue fixed. There are other serious problems with the type system implementation, eg: https://d.puremagic.com/issues/show_bug.cgi?id=9149 https://d.puremagic.com/issues/show_bug.cgi?id=10376 https://d.puremagic.com/issues/show_bug.cgi?id=9148 Thanks, will take those under advisement. FWIW there's been a thread taking suggestions. ... (I know; at that time I didn't think those issues would qualify. :o)) On a related note, I think it makes no sense to put a bounty on the "Object not const-correct" issue. What would someone be required to do in order to get the bounty for that issue? Make sure we have a complete solution for invoking Object's methods against const and immutable Objects? Andrei Wasn't there a consensus that Object's methods are going away?
Re: immutable bug?
On 13 January 2014 07:06, Johnny Walking wrote: > On Saturday, 11 January 2014 at 18:29:36 UTC, Manu wrote: > >> ... >> > > I'm just a bit confused, but recently I've seen many topics from > Manu and problems which he's facing with D. > > So my question is: You don't had any problems when coding > "Remedy's" 3D engine integration with D back then? > (http://dconf.org/2013/talks/evans_1.html) or am I missing > something? > I was doing very different work at that point, stressing totally different parts of the language - mostly meta stuff. And believe me, I had bugs, lots of them. I also had a direct hotline to Walter... I don't feel I have the authority to pester him directly or as frequently now ;) What doesn't come across in my posts is that the D experience today is _so much_ better than it was while I was doing the Remedy work. It's come a long way in terms of quality in the last 1-2 years, and generally gets better every day. I often remark to myself how relatively rare to is to run into compiler bugs today. But you know what seems to reliably make it better? Complaining about it. Well, that... and the work of all the awesome contributors! :) Silently adding workarounds to your code, and dropping a bug somewhere has significantly lesser effect. There's no other functional sense of priority I'm aware of, voting on issues has apparently little meaning. Issues that seem to get the most buzz in the forum seem to get fixed the fastest. I'm good as making noise ;)
Re: immutable bug?
On Monday, 13 January 2014 at 01:07:56 UTC, Manu wrote: On 13 January 2014 07:06, Johnny Walking wrote: On Saturday, 11 January 2014 at 18:29:36 UTC, Manu wrote: ... I'm just a bit confused, but recently I've seen many topics from Manu and problems which he's facing with D. So my question is: You don't had any problems when coding "Remedy's" 3D engine integration with D back then? (http://dconf.org/2013/talks/evans_1.html) or am I missing something? I was doing very different work at that point, stressing totally different parts of the language - mostly meta stuff. And believe me, I had bugs, lots of them. I also had a direct hotline to Walter... I don't feel I have the authority to pester him directly or as frequently now ;) What doesn't come across in my posts is that the D experience today is _so much_ better than it was while I was doing the Remedy work. It's come a long way in terms of quality in the last 1-2 years, and generally gets better every day. I often remark to myself how relatively rare to is to run into compiler bugs today. But you know what seems to reliably make it better? Complaining about it. Well, that... and the work of all the awesome contributors! :) Silently adding workarounds to your code, and dropping a bug somewhere has significantly lesser effect. There's no other functional sense of priority I'm aware of, voting on issues has apparently little meaning. Issues that seem to get the most buzz in the forum seem to get fixed the fastest. I'm good as making noise ;) I know the feeling with Dvorm and Cmsed's router. The amount of bugs I hit are horrendous. I'm not complaining about it or reporting them mainly because a) not on a head build and b) I'm literally pushing the compiler to its limits in some areas. Maybe once next version and it has all been announced I'll start on getting the common issues that a user might experience reported. But I suspect with these ones they aren't gonna be a simple fix. Although I am glad I am doing it now rather than a year ago. Mainly because I've learnt so much since then from the D community. I have to say more than any other in my past.
Re: immutable bug?
On Sunday, 12 January 2014 at 19:36:10 UTC, David Nadlinger wrote: On Sunday, 12 January 2014 at 18:09:59 UTC, Andrei Alexandrescu wrote: Put $150 on this. https://www.bountysource.com/issues/1325974-type-system-breaking-caused-by-implicit-conversion-for-the-value-returned-from-pure-function I posted a fix for this issue (i.e. the one on which the bounty was set). Now tackling Manu's example, which turns out to exhibit a slightly different bug. Filed as https://d.puremagic.com/issues/show_bug.cgi?id=11909, fix at https://github.com/D-Programming-Language/dmd/pull/3085. David
Re: immutable bug?
On 1/12/14 5:46 PM, Rikki Cattermole wrote: I know the feeling with Dvorm and Cmsed's router. The amount of bugs I hit are horrendous. I'm not complaining about it or reporting them mainly because a) not on a head build and b) I'm literally pushing the compiler to its limits in some areas. Please, report all of the bugs. An unreported bug is rather less likely to be fixed. We'd much rather have duplicate reports than no reports. Dups are fairly easy to deal with.
Re: immutable bug?
On Monday, 13 January 2014 at 03:45:07 UTC, Brad Roberts wrote: On 1/12/14 5:46 PM, Rikki Cattermole wrote: I know the feeling with Dvorm and Cmsed's router. The amount of bugs I hit are horrendous. I'm not complaining about it or reporting them mainly because a) not on a head build and b) I'm literally pushing the compiler to its limits in some areas. Please, report all of the bugs. An unreported bug is rather less likely to be fixed. We'd much rather have duplicate reports than no reports. Dups are fairly easy to deal with. I do agree that they need to be dealt with. I'm just not prepared right now to sort out getting the case for each sort of issue I have.
Re: immutable bug?
On 13/01/14 02:07 , Manu wrote: What doesn't come across in my posts is that the D experience today is _so much_ better than it was while I was doing the Remedy work. It's come a long way in terms of quality in the last 1-2 years, and generally gets better every day. I often remark to myself how relatively rare to is to run into compiler bugs today. That's good to hear as for someone that's just (at this stage) lurking around on this mailinglist it's easy to get a very different impression based on the type of discussions. -- Guido Kollerie signature.asc Description: OpenPGP digital signature
Re: immutable bug?
On 13 January 2014 20:03, Guido Kollerie wrote: > On 13/01/14 02:07 , Manu wrote: > > What doesn't come across in my posts is that the D experience today is >> _so much_ better than it was while I was doing the Remedy work. It's >> come a long way in terms of quality in the last 1-2 years, and generally >> gets better every day. >> I often remark to myself how relatively rare to is to run into compiler >> bugs today. >> > > That's good to hear as for someone that's just (at this stage) lurking > around on this mailinglist it's easy to get a very different impression > based on the type of discussions. Well it's a dev forum. I'm sure it's easy to get that impression, since almost all discussion is about things that are broken and people are working on, or ideas for improvement ;)
initialization immutable array
DMD 2.065 I do not know much English. sorry. need to initialize immutable array "_items" //--- module main; import std.stdio; class Zond { this() { foreach (i; 1..4) { _items ~= i; // is expected ERROR } } immutable(int[]) _items; } int main(string[] args) { // create auto zond = new Zond(); // test output foreach (it; zond._items) { writeln(it); } return 0; } //--- this method does not work: Error: field _items initializing not allowed in loops or after labels. OK! is expected - I read in a book Alexandrescu. Make a small change, I add a nested function "addItem": //--- module main; import std.stdio; class Zond { this() { void addItem(in int value) { _items ~= value; // OK , why? } foreach (i; 1..4) { addItem(i); } } immutable(int[]) _items; } int main(string[] args) { // create auto zond = new Zond(); // test output foreach (it; zond._items) { writeln(it); } return 0; } //--- This method initialization works. why? I do not understand the difference.