Re: Weird timing issue with Thread.sleep
On 2011-08-03 20:36, Andrej Mitrovic wrote: On 8/3/11, Jacob Carlborg wrote: Why would you want to slow down framerate? Because the examples were written in the 90s and CPUs and graphic cards are so fast these days that the old code runs at an enormous framerate. I would say that the correct solution is to rewrite the examples to work with any CPU speed. But as you say, it's examples, may not be worth it. -- /Jacob Carlborg
Re: NaCl stable ABI
"Andrej Mitrovic" wrote in message news:mailman.2097.1312408853.14074.digitalmars-d-le...@puremagic.com... >I liked QLive before they forced 30 second commercials on server joins > for non-subscribers. :( > > It was cool being able to casually browse to other tabs, then going > back to qlive and finding a game. > > UT for example had an integrated IRC client, but people preferred > using mIRC and having a ut://123.123.123.123 protocol they can just > click on to join a game. Don't forget having to minimize all the time > to chat to someone on MSN while playing a game. So there are some > benefits to having a browser based interface for a game, imo. There is nothing you've mentioned that can't be (better) fixed without cramming everything into a browser.
Re: NaCl stable ABI
I liked QLive before they forced 30 second commercials on server joins for non-subscribers. :( It was cool being able to casually browse to other tabs, then going back to qlive and finding a game. UT for example had an integrated IRC client, but people preferred using mIRC and having a ut://123.123.123.123 protocol they can just click on to join a game. Don't forget having to minimize all the time to chat to someone on MSN while playing a game. So there are some benefits to having a browser based interface for a game, imo.
Re: NaCl stable ABI
"Nick Sabalausky" wrote in message news:j1cb3a$2qe7$1...@digitalmars.com... > > I mean this is the stupid motherfuck industry that's spent the last ten > years completely ignoring who they're *supposed* to be (***VIDEOGAME*** > developers) and instead running around as a bunch of goddamn > graphics-whore, "storytime", Pixar/Hollywood wannabe, IP-fellatiatng, > fucking posers. Especially the absolutely disgraceful graphics-whore and > "Pixar/Hollywood wannabe" parts. Those two in particular can't be > over-emphasized. > Oh, and how could I forget the other major evidence of the industry's asinine mentality: Seriously, this indistry is holding onto DRM and closed-platforms about 10x harder than the *music* industry, for fuck's sake. And the long-hated music industry has never done region coding - another thing the so-called "videogame" industry (really the "hollywood-wannabe" industry, like I said) is keeping a deathgrip on.
Re: NaCl stable ABI
"Peter Alexander" wrote in message news:j1asck$81d$1...@digitalmars.com... > > The games industry has been crying out for something like NaCl for a long > time. It is exactly what we want: > > - Ability to launch games within browser without a plugin download > - Platform independent ABI > - No f*cking Javascript (performance will never match C++) > - Safe (no need for end users to worry) > > > JavaScript for high-quality games is a non-starter. It's too slow. Browser for "high-quality" games is a non-starter. What idiot would rather play a game inside a damn browser? You could have all the speed in the world, and the browser would still be completely unsuitable for anything beyond dinky little popcap-style shit. We've had Quake playable in the browser for awhile now: and who the hell actually plays it that way? And who actually wants to? It's nothing but a "Gee whiz, look what we can do in a browser!" dick-measuring contest. The whole premise of games in a browser is idiotic. What is needed is 0install and an OS-level security model that's actually good, or something along those lines. None of this Google-mentality "pretending the browser is a platform" bullshit. The browser is a complete strawman here; cramming games into it is solving the wrong issue. It's exactly the old web-app trend all over again: People thought web-based stuff made deployment easier (in a few different ways: not all of which were actually true) and thought that it was safe/secure (which, frankly, has never really been true). So instead of *soving those issues* by putting their focus on improving deployment of *real* apps (via something like 0install) and pushing for improved OS security models (via something like selinux maybe? Seriously how much push is actualyl behind that? Not nearly enough), the morons started cramming apps into the browser (well, that and Valve's Steam abomination) and consequently fucked up computing while *still* not solving half the issues they thought they were solving anyway. If the games industry is crying out for faster in-browser computing, then what they're asking for is a faster horse. But it figures: I mean this is the stupid motherfuck industry that's spent the last ten years completely ignoring who they're *supposed* to be (***VIDEOGAME*** developers) and instead running around as a bunch of goddamn graphics-whore, "storytime", Pixar/Hollywood wannabe, IP-fellatiatng, fucking posers. Especially the absolutely disgraceful graphics-whore and "Pixar/Hollywood wannabe" parts. Those two in particular can't be over-emphasized.
Re: Weird timing issue with Thread.sleep
On 8/3/11, Andrej Mitrovic wrote: > if ((t - t_prev).usecs > (1_000_000.0 / FPS)) > { > t_prev = t; > DrawGLScene(); > } > > SwapBuffers(hDC); My mistake here, SwapBuffers belongs inside the if body, there's an unrelated keyboard bug that made me push it there but I've found what's causing it. Anyway this is offtopic.
Re: "" gives an empty string, while "".idup gives null
On 03.08.2011 22:26, simendsjo wrote: On 03.08.2011 19:15, Jonathan M Davis wrote: On 03.08.2011 18:18, Jonathan M Davis wrote: On Thursday 04 August 2011 00:27:12 Mike Parker wrote: On 8/3/2011 11:23 PM, simendsjo wrote: On 03.08.2011 15:49, bearophile wrote: simendsjo: void main() { assert(is(typeof("") == typeof("".idup))); // both is immutable(char)[] assert("" !is null); assert("".idup !is null); // fails - s is null. Why? } I think someone has even suggested to statically forbid "is null" on strings :-) Bye, bearophile How should I test for null if not with "is null"? There is a difference between null and empty, and avoiding this is not necessarily easy or even wanted. I couldn't find anything in the specification stating this difference. So... Is it a bug? This is apparently a bug. Somehow, the idup is clobbering the pointer. You can see it more clearly here: void main() { assert("".ptr); auto s = "".idup; assert(s.ptr); // boom! } I don't know if it's a bug or not. The string _was_ duped. assert(s == "") passes. So, as far as equality goes, they're equal, and they don't point to the same memory. Now, you'd think that the new string would be just empty rather than null, but whether it's a bug or not depends exactly on what dup and idup are supposed to do with regards to null. It's probably just a side effect of how dup and idup are implemented rather than it being planned one way or the other. I don't know if it matters or not though. In general, I don't like the conflation of null and empty, but is this particular case, you _do_ get a string which is equal to the original and which doesn't point to the same memory. So, I don't know whether this should be considered a bug or not. It depends on what dup and idup are ultimately supposed to do. - Jonathan M Davis I would think it's a bug, but strings doesn't quite behave as regular references anyway... But why should dup/idup change the semantics of the array? void main() { // A null string or empty string works as expected string s1; assert(s1 is null); assert(s1.ptr is null); assert(s1 == ""); // We can check for empty even if it's null, and it's equal to "" assert(s1.length == 0); // ...and length even if it's null s1 = ""; assert(s1 !is null); assert(s1.ptr !is null); assert(s1.length == 0); assert(s1 == ""); // the same applies to null mutable arrays char[] s2; assert(s2 is null); assert(s2.ptr is null); assert(s2 == ""); assert(s2.length == 0); // but with .dup/.idup things is different! s2 = "".dup; //assert(s2 !is null); // fails //assert(s2.ptr !is null); // fails assert(s2.length == 0); // but... s2 is null..? assert(s2 == ""); assert(s2 == s1); } If you look at the spec ( http://d-programming-language.org/arrays.html ), it says: dup: Create a dynamic array of the same size and copy the contents of the array into it. idup: Create a dynamic array of the same size and copy the contents of the array into it. The copy is typed as being immutable. D 2.0 only This is _exactly_ what dup and idup are doing. You get a new array with the exact same size and contents. null doesn't factor into it at all. So, per the spec, there's no bug here at all. dup and idup promise _nothing_ with regards to null. It may be that it would be better if dup and idup returned an array which was null if the original was null, and that would also be within the spec, but what dup and idup do at the moment _does_ follow the spec. So, feel free to file a bug report on it. Maybe it'll get changed, but the current behavior follows the spec. And given how arrays don't generally treat empty and null as being different, I wouldn't really expect an array to stay null if you do _anything_ to it other than simply pass it around or check its value. In this case, you're creating a new array, and D just doesn't generally care about null vs empty when it comes to arrays. I wouldn't argue that that's a good thing (because I don't really think that it is), but because of that, you can't really expect much to treat null and empty as being different. And in this particular case, it's not only debatable as to whether it matters, but the current behavior is completely within the spec. - Jonathan M Davis Schveighoffer also states it is as designed. But it really doesn't behave as one (at least I) would expect. So in essence (as bearophile says), "is null" should not be used on arrays. I was bitten by a bug because of this, and used "" intead of "".idup to avoid this, but given D doesn't distinguish between empty and null arrays, this doesn't feel very safe now.. In the code in question I have a lazy initialized string. The problem is that I would see if it has been initialized, but an empty string is also a valid value. Because I shouldn't check for null, I now have to add another field to the struct to see if the array has been initialized. This feels like a really suboptimal solution. length works e
Re: "" gives an empty string, while "".idup gives null
On Wed, 03 Aug 2011 14:26:54 -0400, simendsjo wrote: Schveighoffer also states it is as designed. But it really doesn't behave as one (at least I) would expect. So in essence (as bearophile says), "is null" should not be used on arrays. I was bitten by a bug because of this, and used "" intead of "".idup to avoid this, but given D doesn't distinguish between empty and null arrays, this doesn't feel very safe now.. I would recommend against depending on the difference between null and not-null-but-empty arrays. But in any case, "".idup is mainly pointless, there is never a need to idup a string, since it's already immutable (and therefore can be passed wherever you need it). In the code in question I have a lazy initialized string. The problem is that I would see if it has been initialized, but an empty string is also a valid value. Because I shouldn't check for null, I now have to add another field to the struct to see if the array has been initialized. This feels like a really suboptimal solution. Where is it that you need to use idup? I think you may be using that without need (or if you are using code that violates immutability, that code is incorrect), but I don't know what your code looks like so I might be wrong. In any case, there may be a better way to do what you want, without the extra field. At the very least, here is a function that can help you: myIdup(string s) { return s.length == 0 ? "" : s.idup; } Note that this kind of thing *ONLY* works for strings, because string literals are not null. For normal arrays, I wouldn't expect this to work. -Steve
Re: "" gives an empty string, while "".idup gives null
> On 03.08.2011 19:15, Jonathan M Davis wrote: > >> On 03.08.2011 18:18, Jonathan M Davis wrote: > >>> On Thursday 04 August 2011 00:27:12 Mike Parker wrote: > On 8/3/2011 11:23 PM, simendsjo wrote: > > On 03.08.2011 15:49, bearophile wrote: > >> simendsjo: > >>> void main() { > >>> assert(is(typeof("") == typeof("".idup))); // both is > >>> immutable(char)[] > >>> > >>> assert("" !is null); > >>> assert("".idup !is null); // fails - s is null. Why? > >>> } > >> > >> I think someone has even suggested to statically forbid "is null" on > >> strings :-) > >> > >> Bye, > >> bearophile > > > > How should I test for null if not with "is null"? There is a > > difference between null and empty, and avoiding this is not > > necessarily easy or even wanted. > > I couldn't find anything in the specification stating this > > difference. So... Is it a bug? > > This is apparently a bug. Somehow, the idup is clobbering the pointer. > You can see it more clearly here: > > void main() > { > > assert("".ptr); > > auto s = "".idup; > assert(s.ptr); // boom! > > } > >>> > >>> I don't know if it's a bug or not. The string _was_ duped. assert(s == > >>> "") passes. So, as far as equality goes, they're equal, and they don't > >>> point to the same memory. Now, you'd think that the new string would be > >>> just empty rather than null, but whether it's a bug or not depends > >>> exactly on what dup and idup are supposed to do with regards to null. > >>> It's probably just a side effect of how dup and idup are implemented > >>> rather than it being planned one way or the other. I don't know if it > >>> matters or not though. In general, I don't like the conflation of null > >>> and empty, but is this particular case, you _do_ get a string which is > >>> equal to the original and which doesn't point to the same memory. So, I > >>> don't know whether this should be considered a bug or not. It depends > >>> on what dup and idup are ultimately supposed to do. > >>> > >>> - Jonathan M Davis > >> > >> I would think it's a bug, but strings doesn't quite behave as regular > >> references anyway... > >> But why should dup/idup change the semantics of the array? > >> > >> void main() { > >> // A null string or empty string works as expected > >> string s1; > >> assert(s1 is null); > >> assert(s1.ptr is null); > >> assert(s1 == ""); // We can check for empty even if it's > >> null, and it's equal to "" > >> assert(s1.length == 0); // ...and length even if it's null > >> s1 = ""; > >> assert(s1 !is null); > >> assert(s1.ptr !is null); > >> assert(s1.length == 0); > >> assert(s1 == ""); > >> > >> // the same applies to null mutable arrays > >> char[] s2; > >> assert(s2 is null); > >> assert(s2.ptr is null); > >> assert(s2 == ""); > >> assert(s2.length == 0); > >> // but with .dup/.idup things is different! > >> s2 = "".dup; > >> //assert(s2 !is null); // fails > >> //assert(s2.ptr !is null); // fails > >> assert(s2.length == 0); // but... s2 is null..? > >> assert(s2 == ""); > >> assert(s2 == s1); > >> } > > > > If you look at the spec ( http://d-programming-language.org/arrays.html > > ), it says: > > > > dup: Create a dynamic array of the same size and copy the contents of > > the array into it. > > > > idup: Create a dynamic array of the same size and copy the contents of > > the array into it. The copy is typed as being immutable. D 2.0 only > > > > > > This is _exactly_ what dup and idup are doing. You get a new array with > > the exact same size and contents. null doesn't factor into it at all. > > So, per the spec, there's no bug here at all. dup and idup promise > > _nothing_ with regards to null. > > > > It may be that it would be better if dup and idup returned an array which > > was null if the original was null, and that would also be within the > > spec, but what dup and idup do at the moment _does_ follow the spec. > > > > So, feel free to file a bug report on it. Maybe it'll get changed, but > > the current behavior follows the spec. And given how arrays don't > > generally treat empty and null as being different, I wouldn't really > > expect an array to stay null if you do _anything_ to it other than > > simply pass it around or check its value. In this case, you're creating > > a new array, and D just doesn't generally care about null vs empty when > > it comes to arrays. I wouldn't argue that that's a good thing (because I > > don't really think that it is), but because of that, you can't really > > expect much to treat null and empty as being different. And in this > > particular case, it's not only debatable as to whether it matters, but > > the current behavior is completely within the spec. > > > > - Jonathan M Davis > > Schveighoffer also states it is as designed. > But it really doesn't behave as one (at least I) would expect. > So in ess
Re: "" gives an empty string, while "".idup gives null
> On Wed, 03 Aug 2011 06:35:08 -0400, simendsjo wrote: > > void main() { > > > > assert(is(typeof("") == typeof("".idup))); // both is > > > > immutable(char)[] > > > > assert("" !is null); > > assert("".idup !is null); // fails - s is null. Why? > > > > } > > An empty string manifest constant (i.e. string literal) still must have a > valid pointer, because it's mandated that the string have a zero byte > appended to it. This is so you can pass it to C functions which expect > null-terminated strings. > > So essentially, there is a '\0' in memory, and "" points to that character > with a length of 0 > > However, idup calls a runtime function which *purposely* asks to make a > copy. However, it's *NOT* required to copy the 'zero after the string' > part. > > The implementation, knowing that a null array is equivalent to an empty > array, is going to return null to avoid the performance penalty of > allocating a block that won't be used. If you append, it will simply > allocate a block as needed. > > I see no reason the runtime should waste cycles or a perfectly good > 16-byte buffer to give you an empty array. > > Definitely functions as designed, not a bug. If you would like different > behavior, you are going to have to have a really really good use case to > get this changed. Given that if you really wanted the duped string to be empty instead of null, it wouldn't be very hard to write a wrapper function for dup which did that, I'd be _very_ surprised if you could find a use case where dup should allocate for an empty string. I don't generally like the fact that D tends to conflate null and empty, but you're creating a new array here. It's not at all surprising if it ends up null if it has no elements in it. In general though, you need to be fairly careful about where you rely on the difference between empty and null. If any kind of memory allocation occurs to an array and its length is 0, it's pretty much free game as to whether it's empty or null. - Jonathan M Davis
Re: Weird timing issue with Thread.sleep
On Wed, 03 Aug 2011 13:42:34 -0400, Andrej Mitrovic wrote: That could be the reason. I'm testing on Windows. Windows only supports millisecond resolution. A valid solution to this is probably to have anything > 0 and < 1 ms sleep for at least 1ms. Or maybe it can round up to the next ms. For now, you can simply sleep for 1ms. -Steve
Re: Weird timing issue with Thread.sleep
On 8/3/11, Jacob Carlborg wrote: > Why would you want to slow down framerate? Because the examples were written in the 90s and CPUs and graphic cards are so fast these days that the old code runs at an enormous framerate. Anyway, after a bit of googling I've found a solution: enum float FPS = 60.0; auto t_prev = Clock.currSystemTick(); while (!done) { auto t = Clock.currSystemTick(); if ((t - t_prev).usecs > (1_000_000.0 / FPS)) { t_prev = t; DrawGLScene(); } SwapBuffers(hDC); } I can also use currAppTick() which is similar. I'm using "enum float" instead of just "enum FPS" because creeping integer truncation bugs lurk into my code all the time. i.e. I end up having an expression like "var1 / var" evaluate to an integer instead of a float because a variable was declared as an integer. Here's what I mean: enum FPS = 60; void main() { auto fraction = (1 / FPS); // woops, actually returns 0 } Using "enum float FPS = 60;" fixes this. It's a very subtle thing and easily introducable as a bug.
Re: "" gives an empty string, while "".idup gives null
On 03.08.2011 19:15, Jonathan M Davis wrote: On 03.08.2011 18:18, Jonathan M Davis wrote: On Thursday 04 August 2011 00:27:12 Mike Parker wrote: On 8/3/2011 11:23 PM, simendsjo wrote: On 03.08.2011 15:49, bearophile wrote: simendsjo: void main() { assert(is(typeof("") == typeof("".idup))); // both is immutable(char)[] assert("" !is null); assert("".idup !is null); // fails - s is null. Why? } I think someone has even suggested to statically forbid "is null" on strings :-) Bye, bearophile How should I test for null if not with "is null"? There is a difference between null and empty, and avoiding this is not necessarily easy or even wanted. I couldn't find anything in the specification stating this difference. So... Is it a bug? This is apparently a bug. Somehow, the idup is clobbering the pointer. You can see it more clearly here: void main() { assert("".ptr); auto s = "".idup; assert(s.ptr); // boom! } I don't know if it's a bug or not. The string _was_ duped. assert(s == "") passes. So, as far as equality goes, they're equal, and they don't point to the same memory. Now, you'd think that the new string would be just empty rather than null, but whether it's a bug or not depends exactly on what dup and idup are supposed to do with regards to null. It's probably just a side effect of how dup and idup are implemented rather than it being planned one way or the other. I don't know if it matters or not though. In general, I don't like the conflation of null and empty, but is this particular case, you _do_ get a string which is equal to the original and which doesn't point to the same memory. So, I don't know whether this should be considered a bug or not. It depends on what dup and idup are ultimately supposed to do. - Jonathan M Davis I would think it's a bug, but strings doesn't quite behave as regular references anyway... But why should dup/idup change the semantics of the array? void main() { // A null string or empty string works as expected string s1; assert(s1 is null); assert(s1.ptr is null); assert(s1 == ""); // We can check for empty even if it's null, and it's equal to "" assert(s1.length == 0); // ...and length even if it's null s1 = ""; assert(s1 !is null); assert(s1.ptr !is null); assert(s1.length == 0); assert(s1 == ""); // the same applies to null mutable arrays char[] s2; assert(s2 is null); assert(s2.ptr is null); assert(s2 == ""); assert(s2.length == 0); // but with .dup/.idup things is different! s2 = "".dup; //assert(s2 !is null); // fails //assert(s2.ptr !is null); // fails assert(s2.length == 0); // but... s2 is null..? assert(s2 == ""); assert(s2 == s1); } If you look at the spec ( http://d-programming-language.org/arrays.html ), it says: dup: Create a dynamic array of the same size and copy the contents of the array into it. idup: Create a dynamic array of the same size and copy the contents of the array into it. The copy is typed as being immutable. D 2.0 only This is _exactly_ what dup and idup are doing. You get a new array with the exact same size and contents. null doesn't factor into it at all. So, per the spec, there's no bug here at all. dup and idup promise _nothing_ with regards to null. It may be that it would be better if dup and idup returned an array which was null if the original was null, and that would also be within the spec, but what dup and idup do at the moment _does_ follow the spec. So, feel free to file a bug report on it. Maybe it'll get changed, but the current behavior follows the spec. And given how arrays don't generally treat empty and null as being different, I wouldn't really expect an array to stay null if you do _anything_ to it other than simply pass it around or check its value. In this case, you're creating a new array, and D just doesn't generally care about null vs empty when it comes to arrays. I wouldn't argue that that's a good thing (because I don't really think that it is), but because of that, you can't really expect much to treat null and empty as being different. And in this particular case, it's not only debatable as to whether it matters, but the current behavior is completely within the spec. - Jonathan M Davis Schveighoffer also states it is as designed. But it really doesn't behave as one (at least I) would expect. So in essence (as bearophile says), "is null" should not be used on arrays. I was bitten by a bug because of this, and used "" intead of "".idup to avoid this, but given D doesn't distinguish between empty and null arrays, this doesn't feel very safe now.. In the code in question I have a lazy initialized string. The problem is that I would see if it has been initialized, but an empty string is also a valid value. Because I shouldn't check for null, I now have to add another field to the struct to see if the array has been initialized. This feels like a really suboptimal solution.
Re: Weird timing issue with Thread.sleep
On 2011-08-03 19:42, Andrej Mitrovic wrote: That could be the reason. I'm testing on Windows. I was using sleep() as a quick hack around slowing down the framerate of an OpenGL display. There are better way to do this but I didn't have time to find a proper solution yet. Why would you want to slow down framerate? -- /Jacob Carlborg
Re: Weird timing issue with Thread.sleep
That could be the reason. I'm testing on Windows. I was using sleep() as a quick hack around slowing down the framerate of an OpenGL display. There are better way to do this but I didn't have time to find a proper solution yet.
Re: Weird timing issue with Thread.sleep
On Wed, 03 Aug 2011 13:14:50 -0400, Andrej Mitrovic wrote: Take a look at this: import std.stdio; import core.thread; void main() { foreach (x; 0 .. 1000) { Thread.sleep(dur!("usecs")(999)); writeln(x); } foreach (x; 0 .. 1000) { Thread.sleep(dur!("usecs")(1000)); writeln(x); } } Compile and run it. The first foreach loop ends in an instant, while the second one takes much much longer to finish, which is puzzling since I've only increased the sleep while for a single microsecond. What's going on? I can only imagine that the cause is the implementation is using an OS function that only supports millisecond sleep resolution. So essentially it's like sleeping for 0 or 1 millisecond. However, without knowing your OS, it's hard to say what's going on. On my linux install, the timing seems equivalent. -Steve
Re: "" gives an empty string, while "".idup gives null
On Wed, 03 Aug 2011 06:35:08 -0400, simendsjo wrote: void main() { assert(is(typeof("") == typeof("".idup))); // both is immutable(char)[] assert("" !is null); assert("".idup !is null); // fails - s is null. Why? } An empty string manifest constant (i.e. string literal) still must have a valid pointer, because it's mandated that the string have a zero byte appended to it. This is so you can pass it to C functions which expect null-terminated strings. So essentially, there is a '\0' in memory, and "" points to that character with a length of 0 However, idup calls a runtime function which *purposely* asks to make a copy. However, it's *NOT* required to copy the 'zero after the string' part. The implementation, knowing that a null array is equivalent to an empty array, is going to return null to avoid the performance penalty of allocating a block that won't be used. If you append, it will simply allocate a block as needed. I see no reason the runtime should waste cycles or a perfectly good 16-byte buffer to give you an empty array. Definitely functions as designed, not a bug. If you would like different behavior, you are going to have to have a really really good use case to get this changed. -Steve
Re: "" gives an empty string, while "".idup gives null
> On 03.08.2011 18:18, Jonathan M Davis wrote: > > On Thursday 04 August 2011 00:27:12 Mike Parker wrote: > >> On 8/3/2011 11:23 PM, simendsjo wrote: > >>> On 03.08.2011 15:49, bearophile wrote: > simendsjo: > > void main() { > > assert(is(typeof("") == typeof("".idup))); // both is > > immutable(char)[] > > > > assert("" !is null); > > assert("".idup !is null); // fails - s is null. Why? > > } > > I think someone has even suggested to statically forbid "is null" on > strings :-) > > Bye, > bearophile > >>> > >>> How should I test for null if not with "is null"? There is a difference > >>> between null and empty, and avoiding this is not necessarily easy or > >>> even wanted. > >>> I couldn't find anything in the specification stating this difference. > >>> So... Is it a bug? > >> > >> This is apparently a bug. Somehow, the idup is clobbering the pointer. > >> You can see it more clearly here: > >> > >> void main() > >> { > >> > >> assert("".ptr); > >> > >> auto s = "".idup; > >> assert(s.ptr); // boom! > >> > >> } > > > > I don't know if it's a bug or not. The string _was_ duped. assert(s == > > "") passes. So, as far as equality goes, they're equal, and they don't > > point to the same memory. Now, you'd think that the new string would be > > just empty rather than null, but whether it's a bug or not depends > > exactly on what dup and idup are supposed to do with regards to null. > > It's probably just a side effect of how dup and idup are implemented > > rather than it being planned one way or the other. I don't know if it > > matters or not though. In general, I don't like the conflation of null > > and empty, but is this particular case, you _do_ get a string which is > > equal to the original and which doesn't point to the same memory. So, I > > don't know whether this should be considered a bug or not. It depends on > > what dup and idup are ultimately supposed to do. > > > > - Jonathan M Davis > > I would think it's a bug, but strings doesn't quite behave as regular > references anyway... > But why should dup/idup change the semantics of the array? > > void main() { > // A null string or empty string works as expected > string s1; > assert(s1 is null); > assert(s1.ptr is null); > assert(s1 == ""); // We can check for empty even if it's > null, and it's equal to "" > assert(s1.length == 0); // ...and length even if it's null > s1 = ""; > assert(s1 !is null); > assert(s1.ptr !is null); > assert(s1.length == 0); > assert(s1 == ""); > > // the same applies to null mutable arrays > char[] s2; > assert(s2 is null); > assert(s2.ptr is null); > assert(s2 == ""); > assert(s2.length == 0); > // but with .dup/.idup things is different! > s2 = "".dup; > //assert(s2 !is null); // fails > //assert(s2.ptr !is null); // fails > assert(s2.length == 0); // but... s2 is null..? > assert(s2 == ""); > assert(s2 == s1); > } If you look at the spec ( http://d-programming-language.org/arrays.html ), it says: dup: Create a dynamic array of the same size and copy the contents of the array into it. idup: Create a dynamic array of the same size and copy the contents of the array into it. The copy is typed as being immutable. D 2.0 only This is _exactly_ what dup and idup are doing. You get a new array with the exact same size and contents. null doesn't factor into it at all. So, per the spec, there's no bug here at all. dup and idup promise _nothing_ with regards to null. It may be that it would be better if dup and idup returned an array which was null if the original was null, and that would also be within the spec, but what dup and idup do at the moment _does_ follow the spec. So, feel free to file a bug report on it. Maybe it'll get changed, but the current behavior follows the spec. And given how arrays don't generally treat empty and null as being different, I wouldn't really expect an array to stay null if you do _anything_ to it other than simply pass it around or check its value. In this case, you're creating a new array, and D just doesn't generally care about null vs empty when it comes to arrays. I wouldn't argue that that's a good thing (because I don't really think that it is), but because of that, you can't really expect much to treat null and empty as being different. And in this particular case, it's not only debatable as to whether it matters, but the current behavior is completely within the spec. - Jonathan M Davis
Re: Weird timing issue with Thread.sleep
s/sleep while/sleep value
Weird timing issue with Thread.sleep
Take a look at this: import std.stdio; import core.thread; void main() { foreach (x; 0 .. 1000) { Thread.sleep(dur!("usecs")(999)); writeln(x); } foreach (x; 0 .. 1000) { Thread.sleep(dur!("usecs")(1000)); writeln(x); } } Compile and run it. The first foreach loop ends in an instant, while the second one takes much much longer to finish, which is puzzling since I've only increased the sleep while for a single microsecond. What's going on?
Re: "" gives an empty string, while "".idup gives null
On 03.08.2011 18:18, Jonathan M Davis wrote: On Thursday 04 August 2011 00:27:12 Mike Parker wrote: On 8/3/2011 11:23 PM, simendsjo wrote: On 03.08.2011 15:49, bearophile wrote: simendsjo: void main() { assert(is(typeof("") == typeof("".idup))); // both is immutable(char)[] assert("" !is null); assert("".idup !is null); // fails - s is null. Why? } I think someone has even suggested to statically forbid "is null" on strings :-) Bye, bearophile How should I test for null if not with "is null"? There is a difference between null and empty, and avoiding this is not necessarily easy or even wanted. I couldn't find anything in the specification stating this difference. So... Is it a bug? This is apparently a bug. Somehow, the idup is clobbering the pointer. You can see it more clearly here: void main() { assert("".ptr); auto s = "".idup; assert(s.ptr); // boom! } I don't know if it's a bug or not. The string _was_ duped. assert(s == "") passes. So, as far as equality goes, they're equal, and they don't point to the same memory. Now, you'd think that the new string would be just empty rather than null, but whether it's a bug or not depends exactly on what dup and idup are supposed to do with regards to null. It's probably just a side effect of how dup and idup are implemented rather than it being planned one way or the other. I don't know if it matters or not though. In general, I don't like the conflation of null and empty, but is this particular case, you _do_ get a string which is equal to the original and which doesn't point to the same memory. So, I don't know whether this should be considered a bug or not. It depends on what dup and idup are ultimately supposed to do. - Jonathan M Davis I would think it's a bug, but strings doesn't quite behave as regular references anyway... But why should dup/idup change the semantics of the array? void main() { // A null string or empty string works as expected string s1; assert(s1 is null); assert(s1.ptr is null); assert(s1 == ""); // We can check for empty even if it's null, and it's equal to "" assert(s1.length== 0); // ...and length even if it's null s1 = ""; assert(s1 !is null); assert(s1.ptr !is null); assert(s1.length== 0); assert(s1 == ""); // the same applies to null mutable arrays char[] s2; assert(s2 is null); assert(s2.ptr is null); assert(s2 == ""); assert(s2.length== 0); // but with .dup/.idup things is different! s2 = "".dup; //assert(s2 !is null); // fails //assert(s2.ptr !is null); // fails assert(s2.length== 0); // but... s2 is null..? assert(s2 == ""); assert(s2 == s1); }
Re: Hexadecimal string to integer
On 3/08/2011 2:32, Johann MacDonagh wrote: On 8/2/2011 8:17 PM, Stijn Herreman wrote: std.conv does not support conversion from a hexadecimal string to an integer. Is there a technical reason for this limitation? This is the best I could do, can it be improved still? int i = to!int(parse!float("0x1ap0")); parse!int("1a", 16); I tried multiple combinations but not that one, thanks.
Re: "" gives an empty string, while "".idup gives null
On Thursday 04 August 2011 00:27:12 Mike Parker wrote: > On 8/3/2011 11:23 PM, simendsjo wrote: > > On 03.08.2011 15:49, bearophile wrote: > >> simendsjo: > >>> void main() { > >>> assert(is(typeof("") == typeof("".idup))); // both is > >>> immutable(char)[] > >>> > >>> assert("" !is null); > >>> assert("".idup !is null); // fails - s is null. Why? > >>> } > >> > >> I think someone has even suggested to statically forbid "is null" on > >> strings :-) > >> > >> Bye, > >> bearophile > > > > How should I test for null if not with "is null"? There is a difference > > between null and empty, and avoiding this is not necessarily easy or > > even wanted. > > I couldn't find anything in the specification stating this difference. > > So... Is it a bug? > > This is apparently a bug. Somehow, the idup is clobbering the pointer. > You can see it more clearly here: > > void main() > { > assert("".ptr); > > auto s = "".idup; > assert(s.ptr); // boom! > } I don't know if it's a bug or not. The string _was_ duped. assert(s == "") passes. So, as far as equality goes, they're equal, and they don't point to the same memory. Now, you'd think that the new string would be just empty rather than null, but whether it's a bug or not depends exactly on what dup and idup are supposed to do with regards to null. It's probably just a side effect of how dup and idup are implemented rather than it being planned one way or the other. I don't know if it matters or not though. In general, I don't like the conflation of null and empty, but is this particular case, you _do_ get a string which is equal to the original and which doesn't point to the same memory. So, I don't know whether this should be considered a bug or not. It depends on what dup and idup are ultimately supposed to do. - Jonathan M Davis
Re: NaCl stable ABI
Peter Alexander wrote: > If D were usable in NaCl that would be a huge selling point for the > language. Well, let's set aside my personal things and see how this might be done. Based on what I've read so far, it actually sounds easy enough, codegen wise. It might be possible to drop gdc into their hacked up gcc backend and have it work with minimal effort. Or, changing dmd's backend to emit code for it might not be hard either. It looks like it'd just have to align jumps, which should be as simple as padding labels with some nops. The bigger difficulty I suspect will be porting the runtime... but, since it builds on C in a lot of places, that might be simple too. I can't find more details on what's needed to happen to the compilers, but I'm really thinking it won't be very difficult to make it happen.
Re: "" gives an empty string, while "".idup gives null
On 8/3/2011 11:23 PM, simendsjo wrote: On 03.08.2011 15:49, bearophile wrote: simendsjo: void main() { assert(is(typeof("") == typeof("".idup))); // both is immutable(char)[] assert("" !is null); assert("".idup !is null); // fails - s is null. Why? } I think someone has even suggested to statically forbid "is null" on strings :-) Bye, bearophile How should I test for null if not with "is null"? There is a difference between null and empty, and avoiding this is not necessarily easy or even wanted. I couldn't find anything in the specification stating this difference. So... Is it a bug? This is apparently a bug. Somehow, the idup is clobbering the pointer. You can see it more clearly here: void main() { assert("".ptr); auto s = "".idup; assert(s.ptr); // boom! }
Re: GG bug? (OS X Lion, DMD 2.054)
On 8/3/11 4:07 PM, Magnus Lie Hetland wrote: I upgraded from OS X Snow Leopard to Lion recently (on a 32-bit iMac), and when I tried to run my D code afterward, I suddenly ran into all kinds of interesting problems (lots of failed assertions in my tests, and bus errors in my actual runs...). This seems to be exactly same problem I reported to the NG some days ago. It is caused by ASLR being enabled for 32bit applications on Lion too, and kennytm is to be credited for tracking this down to a fixed stack bottom in the druntime code: https://github.com/D-Programming-Language/druntime/pull/43. The fix has already been merged into master, please use that for OS X development until the next DMD release. David
Re: "" gives an empty string, while "".idup gives null
On 03.08.2011 15:49, bearophile wrote: simendsjo: void main() { assert(is(typeof("") == typeof("".idup))); // both is immutable(char)[] assert("" !is null); assert("".idup !is null); // fails - s is null. Why? } I think someone has even suggested to statically forbid "is null" on strings :-) Bye, bearophile How should I test for null if not with "is null"? There is a difference between null and empty, and avoiding this is not necessarily easy or even wanted. I couldn't find anything in the specification stating this difference. So... Is it a bug?
Re: GG bug? (OS X Lion, DMD 2.054)
Note that an explicit call to GC.collect isn't necessary. Whenever collection occurs, the collectors seems rather indiscriminate, collecting things it shouldn't, resulting in bus errors. When I disable the GC, my code runs just fine. (My production code, that is. There are still mysterious, probably Lion-related, bugs in my test suite...) -- Magnus Lie Hetland http://hetland.org
GG bug? (OS X Lion, DMD 2.054)
I upgraded from OS X Snow Leopard to Lion recently (on a 32-bit iMac), and when I tried to run my D code afterward, I suddenly ran into all kinds of interesting problems (lots of failed assertions in my tests, and bus errors in my actual runs...). Still cleaning stuff up, but I've isolated at least one thing that seems to be a bug, and that wasn't there before I upgraded. Now, I upgraded from DMD 2.052 to 2.054 before doing any extensive debugging, so I'm not 100% sure this specific problem was there in 2.052 as well, but I *think* so (i.e., making the switch to Lion the triggering factor). Anyway, here's some code: import std.exception, core.memory; class Foo { bool bar; } void main() { auto f = new Foo; f.bar = true; //GC.collect(); enforce(f.bar); } Works well, unless you uncomment the GC call, in which case a bus error occurs (at least for me). Seems the collector is a bit over-eager...? -- Magnus Lie Hetland http://hetland.org
Re: "" gives an empty string, while "".idup gives null
simendsjo: > void main() { > assert(is(typeof("") == typeof("".idup))); // both is immutable(char)[] > > assert("" !is null); > assert("".idup !is null); // fails - s is null. Why? > } I think someone has even suggested to statically forbid "is null" on strings :-) Bye, bearophile
Re: Convert string to wchar.
On 2011-08-03 09:34, Pelle wrote: On Wed, 03 Aug 2011 08:29:09 +0200, Jacob Carlborg wrote: Yes, convert the first code point to a wchar and then throw if there's more the one character in the string. Not tested, and I might be wrong, but 'to!' should work between dchar and wchar, no? wchar to_wchar(string s) { auto c = s.front; s.popFront(); assert (s.empty); return to!wchar(c); } Ok, thanks. -- /Jacob Carlborg
Re: Convert string to wchar.
On 2011-08-03 08:38, Jonathan M Davis wrote: On Wednesday 03 August 2011 08:29:09 Jacob Carlborg wrote: On 2011-08-02 19:51, Jonathan M Davis wrote: I tried to convert a string into a wchar, but that didn't compile because of this template constraint: https://github.com/D-Programming-Language/phobos/blob/master/std/conv. d#L17 70 Is there a way to convert a string into a wchar? Does that even make sense? What do you want it to do, convert the first code point to a wchar and throw if there's more than one character in the string? That's like asking whether you can covert between a container of ints and an int. I would never expect std.conv.to to support that. Not to mention, you shouldn't normally be using char or wchar by themselves, because they might not be valid code points. Normally, only dchar should be used when representing an individual character. If you want this, I'd suggest that you simply do something like cast(wchar)str.front What you're asking for is inherently unsafe as far as unicode goes. - Jonathan M Davis I'm working on a serialization library and I intend to support as many types as possible. So if someone serializes a single wchar I need to be able to deserialize it. Since the serialized data is represented by a string, in this case, I need to convert a string containing a single character to a wchar when deserializing. Yes, convert the first code point to a wchar and then throw if there's more the one character in the string. Well, while it's understandable that you have to cover pretty every possible case of converting to and from a string with what you're doing, I don't think that it's at all reasonable to have std.conv.to convert a string to any character type, let alone one other than dchar. It's almost always a horrible idea and should _not_ be encouraged. So, I'd advise you to just find a way to deal with it appropriately in your own code. I think that it would be a very bad idea for std.conv.to or anything else in Phobos to support such a conversion. - Jonathan M Davis Ok, fair enough. -- /Jacob Carlborg
"" gives an empty string, while "".idup gives null
void main() { assert(is(typeof("") == typeof("".idup))); // both is immutable(char)[] assert("" !is null); assert("".idup !is null); // fails - s is null. Why? }
Re: Immutable member functions and private members
On 03.08.2011 12:01, Jonathan M Davis wrote: On Wednesday 03 August 2011 11:44:27 simendsjo wrote: On 03.08.2011 10:52, Jonathan M Davis wrote: On Wednesday 03 August 2011 10:37:58 simendsjo wrote: I have a struct with a private member that is only ever accessed through a single property method - even from within the struct. As this property fills the value on the first access, it cannot be immutable, and as such, none of the many methods accessing this property can be immutable methods. This is according to specification, but I thought that since the single write to the property is done at one, and only one, access point, that it would be safe? I could fill this value in the constructor, but it's a bit slow, so I'd rather do it only if needed. And is there any potential performance optimizations done by the compiler, or is it "only" for safety? Is there a way to hack around this, and more importantly, is it safe to do so, or will I open Pandora's box? Small example: int len(const char[] c) { return c.length; } struct S { private immutable(char)[] _v; @property immutable(char[]) v() { // Cannot be immutable method if(!_v) _v = "init"; /* or from external function */ return _v; } @property int a() { // and so this cannot be immutable method return len(v); /* notice the property function v that might modify _v */ } } void main() { S s; s.a; } You're basically looking for logical const - albeit a subset which would be much easier to implement were we to implement it (that is, a lazy initialized const or immutable member variable). D has no support for logical const. Even worse, you're looking for logical immutable (which makes no sense at all beyond perhaps lazy initialization and probably doesn't even make sense there). The thing is that immutable methods are pointless unless you make the struct immutable (if you want to be able to call them with both a mutable and immutable instance of the struct, then you need the functions to be const, not immutable). And if you make the struct immutable, the compiler is free to put it in read-only memory if it so chooses, at which point setting _anything_ in the struct after the constructor has run is likely to blow up. So, even if you can get around the issue via casts and get both lazy initialization and immutable methods, there's a good chance that it'll blow up at some point (as in segfault or worse). If you were trying to do this with const, you might get away with it (though you'd be stepping outside of the type lsystem by casting away const and then altering anything - it's undefined behavior). But with immutable, there's no way that this is a good idea. Lazy initialization with const or immutable member variables just is _not_ a good idea in D. D provides no type-safe way to do this. You must break the type system by casting away const or immutable to even attempt it. Convievably, in the case of const, the language could be extended to allow for lazy initialization of member variables, but there's no way that it could do that with immutable (because the variable could conceivably be put in read- only memory), and even if it were done, it would likely have to be a D3 feature. Syntactically, it would probably be something like this: lazy int v = initFunc(); and then when v was first accessed, initFunc would be called and v set to that value. But that could be ugly and inefficient to implement even if it's theoretically possible, so I wouldn't bet on anything like that making it into the language. Regardless, it wouldn't be until D3. For now, D doesn't support any kind of logical const. http://stackoverflow.com/questions/4219600/logical-const-in-d - Jonathan M Davis Thanks! I'm not really sure the compiler could put my struct in ROM. My lazy parameter is immutable(char)[], so the compiler should see that I have a non-immutable reference. The entire struct is immutable without this lazy variable though. It only has two handles for passing to external functions. I really would like to always use it only as immutable s = S(123). It makes no sense for it to be mutable at all. Below is an exact example of what I want to do. If I move the handle2 calculation to the ctor and use const methods, I still cannot call the methods using a const variable though.. Bug? const s = S(100); s.a; // function t.S.a () immutable is not callable using argument type It says immutable when it should say const..? immutable s = S(100); s.a; // works on both const and immutable If a variable is const, you should only be able to call const functions on it. If it's immutable, you can call either const or immutable functions. If it's mutable, then you can call either const or non-const, non-immutable functions. If it's complaining about being unable to call a function on an immutable variable whe
Re: Immutable member functions and private members
On Wednesday 03 August 2011 12:00:18 simendsjo wrote: > On 03.08.2011 11:44, simendsjo wrote: > > On 03.08.2011 10:52, Jonathan M Davis wrote: > >> On Wednesday 03 August 2011 10:37:58 simendsjo wrote: > >>> I have a struct with a private member that is only ever accessed > >>> through a single property method - even from within the struct. > >>> As this property fills the value on the first access, it cannot be > >>> immutable, and as such, none of the many methods accessing this > >>> property can be immutable methods. > >>> > >>> This is according to specification, but I thought that since the > >>> single > >>> write to the property is done at one, and only one, access point, > >>> that > >>> it would be safe? > >>> > >>> I could fill this value in the constructor, but it's a bit slow, so > >>> I'd > >>> rather do it only if needed. > >>> > >>> And is there any potential performance optimizations done by the > >>> compiler, or is it "only" for safety? > >>> Is there a way to hack around this, and more importantly, is it safe > >>> to > >>> do so, or will I open Pandora's box? > >>> > >>> > >>> Small example: > >>> > >>> int len(const char[] c) { > >>> return c.length; > >>> } > >>> > >>> struct S { > >>> private immutable(char)[] _v; > >>> @property immutable(char[]) v() { // Cannot be immutable method > >>> if(!_v) > >>> _v = "init"; /* or from external function */ > >>> return _v; > >>> } > >>> > >>> @property int a() { // and so this cannot be immutable method > >>> return len(v); /* notice the property function v that might > >>> modify _v */ > >>> } > >>> } > >>> > >>> void main() { > >>> S s; > >>> s.a; > >>> } > >> > >> You're basically looking for logical const - albeit a subset which > >> would be > >> much easier to implement were we to implement it (that is, a lazy > >> initialized > >> const or immutable member variable). D has no support for logical > >> const. Even > >> worse, you're looking for logical immutable (which makes no sense at > >> all > >> beyond perhaps lazy initialization and probably doesn't even make > >> sense > >> there). > >> > >> The thing is that immutable methods are pointless unless you make the > >> struct > >> immutable (if you want to be able to call them with both a mutable and > >> immutable instance of the struct, then you need the functions to be > >> const, not > >> immutable). And if you make the struct immutable, the compiler is free > >> to put > >> it in read-only memory if it so chooses, at which point setting > >> _anything_ in > >> the struct after the constructor has run is likely to blow up. So, > >> even if you > >> can get around the issue via casts and get both lazy initialization > >> and > >> immutable methods, there's a good chance that it'll blow up at some > >> point (as > >> in segfault or worse). > >> > >> If you were trying to do this with const, you might get away with it > >> (though > >> you'd be stepping outside of the type lsystem by casting away const > >> and then > >> altering anything - it's undefined behavior). But with immutable, > >> there's no > >> way that this is a good idea. > >> > >> Lazy initialization with const or immutable member variables just is > >> _not_ a > >> good idea in D. D provides no type-safe way to do this. You must break > >> the > >> type system by casting away const or immutable to even attempt it. > >> Convievably, in the case of const, the language could be extended to > >> allow for > >> lazy initialization of member variables, but there's no way that it > >> could do > >> that with immutable (because the variable could conceivably be put in > >> read- > >> only memory), and even if it were done, it would likely have to be a > >> D3 > >> feature. Syntactically, it would probably be something like this: > >> > >> lazy int v = initFunc(); > >> > >> and then when v was first accessed, initFunc would be called and v set > >> to that > >> value. But that could be ugly and inefficient to implement even if > >> it's > >> theoretically possible, so I wouldn't bet on anything like that making > >> it into > >> the language. Regardless, it wouldn't be until D3. For now, D doesn't > >> support > >> any kind of logical const. > >> > >> http://stackoverflow.com/questions/4219600/logical-const-in-d > >> > >> - Jonathan M Davis > > > > Thanks! > > > > I'm not really sure the compiler could put my struct in ROM. > > My lazy parameter is immutable(char)[], so the compiler should see that > > I have a non-immutable reference. > > > > The entire struct is immutable without this lazy variable though. > > It only has two handles for passing to external functions. > > I really would like to always use it only as immutable s = S(123). It > > makes no sense for it to be mutable at all. > > > > Below is an exact example of what I want to do. > > If I move the handle2 calculation to the ctor and use const methods, I > > still cannot call the methods using a const variable though.. Bug? > > const s = S(10
Re: Immutable member functions and private members
On 03.08.2011 11:44, simendsjo wrote: On 03.08.2011 10:52, Jonathan M Davis wrote: On Wednesday 03 August 2011 10:37:58 simendsjo wrote: I have a struct with a private member that is only ever accessed through a single property method - even from within the struct. As this property fills the value on the first access, it cannot be immutable, and as such, none of the many methods accessing this property can be immutable methods. This is according to specification, but I thought that since the single write to the property is done at one, and only one, access point, that it would be safe? I could fill this value in the constructor, but it's a bit slow, so I'd rather do it only if needed. And is there any potential performance optimizations done by the compiler, or is it "only" for safety? Is there a way to hack around this, and more importantly, is it safe to do so, or will I open Pandora's box? Small example: int len(const char[] c) { return c.length; } struct S { private immutable(char)[] _v; @property immutable(char[]) v() { // Cannot be immutable method if(!_v) _v = "init"; /* or from external function */ return _v; } @property int a() { // and so this cannot be immutable method return len(v); /* notice the property function v that might modify _v */ } } void main() { S s; s.a; } You're basically looking for logical const - albeit a subset which would be much easier to implement were we to implement it (that is, a lazy initialized const or immutable member variable). D has no support for logical const. Even worse, you're looking for logical immutable (which makes no sense at all beyond perhaps lazy initialization and probably doesn't even make sense there). The thing is that immutable methods are pointless unless you make the struct immutable (if you want to be able to call them with both a mutable and immutable instance of the struct, then you need the functions to be const, not immutable). And if you make the struct immutable, the compiler is free to put it in read-only memory if it so chooses, at which point setting _anything_ in the struct after the constructor has run is likely to blow up. So, even if you can get around the issue via casts and get both lazy initialization and immutable methods, there's a good chance that it'll blow up at some point (as in segfault or worse). If you were trying to do this with const, you might get away with it (though you'd be stepping outside of the type lsystem by casting away const and then altering anything - it's undefined behavior). But with immutable, there's no way that this is a good idea. Lazy initialization with const or immutable member variables just is _not_ a good idea in D. D provides no type-safe way to do this. You must break the type system by casting away const or immutable to even attempt it. Convievably, in the case of const, the language could be extended to allow for lazy initialization of member variables, but there's no way that it could do that with immutable (because the variable could conceivably be put in read- only memory), and even if it were done, it would likely have to be a D3 feature. Syntactically, it would probably be something like this: lazy int v = initFunc(); and then when v was first accessed, initFunc would be called and v set to that value. But that could be ugly and inefficient to implement even if it's theoretically possible, so I wouldn't bet on anything like that making it into the language. Regardless, it wouldn't be until D3. For now, D doesn't support any kind of logical const. http://stackoverflow.com/questions/4219600/logical-const-in-d - Jonathan M Davis Thanks! I'm not really sure the compiler could put my struct in ROM. My lazy parameter is immutable(char)[], so the compiler should see that I have a non-immutable reference. The entire struct is immutable without this lazy variable though. It only has two handles for passing to external functions. I really would like to always use it only as immutable s = S(123). It makes no sense for it to be mutable at all. Below is an exact example of what I want to do. If I move the handle2 calculation to the ctor and use const methods, I still cannot call the methods using a const variable though.. Bug? const s = S(100); s.a; // function t.S.a () immutable is not callable using argument type It says immutable when it should say const..? immutable s = S(100); s.a; // works on both const and immutable import std.conv, std.exception; // external expensive function extern(System) char[] getHandle2(const int handle) { return to!(char[])(handle); } // other external functions taking string handle instead of int extern(System) int extFunc1(string handle2) { return to!int(handle2); } struct S { immutable int handle; private immutable(char)[] _handle2; this(int handle) { this.handle = handle; } @property immutable(char[]) handle2() { if(!_handle2) { auto buf = getHandle2(handle); _handle2 = assumeUnique(buf); } return _handle2; } @property int
Re: Immutable member functions and private members
On Wednesday 03 August 2011 11:44:27 simendsjo wrote: > On 03.08.2011 10:52, Jonathan M Davis wrote: > > On Wednesday 03 August 2011 10:37:58 simendsjo wrote: > >> I have a struct with a private member that is only ever accessed > >> through > >> a single property method - even from within the struct. > >> As this property fills the value on the first access, it cannot be > >> immutable, and as such, none of the many methods accessing this > >> property > >> can be immutable methods. > >> > >> This is according to specification, but I thought that since the > >> single > >> write to the property is done at one, and only one, access point, that > >> it would be safe? > >> > >> I could fill this value in the constructor, but it's a bit slow, so > >> I'd > >> rather do it only if needed. > >> > >> And is there any potential performance optimizations done by the > >> compiler, or is it "only" for safety? > >> Is there a way to hack around this, and more importantly, is it safe > >> to > >> do so, or will I open Pandora's box? > >> > >> > >> Small example: > >> > >> int len(const char[] c) { > >> > >> return c.length; > >> > >> } > >> > >> struct S { > >> > >> private immutable(char)[] _v; > >> @property immutable(char[]) v() { // Cannot be immutable > >> method > >> > >> if(!_v) > >> > >> _v = "init"; /* or from external function > >> */ > >> > >> return _v; > >> > >> } > >> > >> @property int a() { // and so this cannot be immutable > >> method > >> > >> return len(v); /* notice the property function v > >> that might > >> > >> modify _v */ > >> > >> } > >> > >> } > >> > >> void main() { > >> > >> S s; > >> s.a; > >> > >> } > > > > You're basically looking for logical const - albeit a subset which would > > be much easier to implement were we to implement it (that is, a lazy > > initialized const or immutable member variable). D has no support for > > logical const. Even worse, you're looking for logical immutable (which > > makes no sense at all beyond perhaps lazy initialization and probably > > doesn't even make sense there). > > > > The thing is that immutable methods are pointless unless you make the > > struct immutable (if you want to be able to call them with both a > > mutable and immutable instance of the struct, then you need the > > functions to be const, not immutable). And if you make the struct > > immutable, the compiler is free to put it in read-only memory if it so > > chooses, at which point setting _anything_ in the struct after the > > constructor has run is likely to blow up. So, even if you can get > > around the issue via casts and get both lazy initialization and > > immutable methods, there's a good chance that it'll blow up at some > > point (as in segfault or worse). > > > > If you were trying to do this with const, you might get away with it > > (though you'd be stepping outside of the type lsystem by casting away > > const and then altering anything - it's undefined behavior). But with > > immutable, there's no way that this is a good idea. > > > > Lazy initialization with const or immutable member variables just is > > _not_ a good idea in D. D provides no type-safe way to do this. You > > must break the type system by casting away const or immutable to even > > attempt it. Convievably, in the case of const, the language could be > > extended to allow for lazy initialization of member variables, but > > there's no way that it could do that with immutable (because the > > variable could conceivably be put in read- only memory), and even if it > > were done, it would likely have to be a D3 feature. Syntactically, it > > would probably be something like this: > > > > lazy int v = initFunc(); > > > > and then when v was first accessed, initFunc would be called and v set > > to that value. But that could be ugly and inefficient to implement even > > if it's theoretically possible, so I wouldn't bet on anything like that > > making it into the language. Regardless, it wouldn't be until D3. For > > now, D doesn't support any kind of logical const. > > > > http://stackoverflow.com/questions/4219600/logical-const-in-d > > > > - Jonathan M Davis > > Thanks! > > I'm not really sure the compiler could put my struct in ROM. > My lazy parameter is immutable(char)[], so the compiler should see that > I have a non-immutable reference. > > The entire struct is immutable without this lazy variable though. > It only has two handles for passing to external functions. > I really would like to always use it only as immutable s = S(123). It > makes no sense for it to be mutable at all. > > Below is an exact example of what I want to do. > If I move the handle2 calculation to the ctor and use const methods, I > still cannot call the methods using a const variable though.. Bug? >const s = S(100);
Re: Immutable member functions and private members
On 03.08.2011 10:52, Jonathan M Davis wrote: On Wednesday 03 August 2011 10:37:58 simendsjo wrote: I have a struct with a private member that is only ever accessed through a single property method - even from within the struct. As this property fills the value on the first access, it cannot be immutable, and as such, none of the many methods accessing this property can be immutable methods. This is according to specification, but I thought that since the single write to the property is done at one, and only one, access point, that it would be safe? I could fill this value in the constructor, but it's a bit slow, so I'd rather do it only if needed. And is there any potential performance optimizations done by the compiler, or is it "only" for safety? Is there a way to hack around this, and more importantly, is it safe to do so, or will I open Pandora's box? Small example: int len(const char[] c) { return c.length; } struct S { private immutable(char)[] _v; @property immutable(char[]) v() { // Cannot be immutable method if(!_v) _v = "init"; /* or from external function */ return _v; } @property int a() { // and so this cannot be immutable method return len(v); /* notice the property function v that might modify _v */ } } void main() { S s; s.a; } You're basically looking for logical const - albeit a subset which would be much easier to implement were we to implement it (that is, a lazy initialized const or immutable member variable). D has no support for logical const. Even worse, you're looking for logical immutable (which makes no sense at all beyond perhaps lazy initialization and probably doesn't even make sense there). The thing is that immutable methods are pointless unless you make the struct immutable (if you want to be able to call them with both a mutable and immutable instance of the struct, then you need the functions to be const, not immutable). And if you make the struct immutable, the compiler is free to put it in read-only memory if it so chooses, at which point setting _anything_ in the struct after the constructor has run is likely to blow up. So, even if you can get around the issue via casts and get both lazy initialization and immutable methods, there's a good chance that it'll blow up at some point (as in segfault or worse). If you were trying to do this with const, you might get away with it (though you'd be stepping outside of the type lsystem by casting away const and then altering anything - it's undefined behavior). But with immutable, there's no way that this is a good idea. Lazy initialization with const or immutable member variables just is _not_ a good idea in D. D provides no type-safe way to do this. You must break the type system by casting away const or immutable to even attempt it. Convievably, in the case of const, the language could be extended to allow for lazy initialization of member variables, but there's no way that it could do that with immutable (because the variable could conceivably be put in read- only memory), and even if it were done, it would likely have to be a D3 feature. Syntactically, it would probably be something like this: lazy int v = initFunc(); and then when v was first accessed, initFunc would be called and v set to that value. But that could be ugly and inefficient to implement even if it's theoretically possible, so I wouldn't bet on anything like that making it into the language. Regardless, it wouldn't be until D3. For now, D doesn't support any kind of logical const. http://stackoverflow.com/questions/4219600/logical-const-in-d - Jonathan M Davis Thanks! I'm not really sure the compiler could put my struct in ROM. My lazy parameter is immutable(char)[], so the compiler should see that I have a non-immutable reference. The entire struct is immutable without this lazy variable though. It only has two handles for passing to external functions. I really would like to always use it only as immutable s = S(123). It makes no sense for it to be mutable at all. Below is an exact example of what I want to do. If I move the handle2 calculation to the ctor and use const methods, I still cannot call the methods using a const variable though.. Bug? const s = S(100); s.a; // function t.S.a () immutable is not callable using argument type It says immutable when it should say const..? immutable s = S(100); s.a; // works on both const and immutable import std.conv, std.exception; // external expensive function extern(System) char[] getHandle2(const int handle) { return to!(char[])(handle); } // other external functions taking string handle instead of int extern(System) int extFunc1(string handle2) { return to!int(handle2); } struct S { immutable int handle; private immutable(char)[] _handle2; this(int handle) { this.handle = handle; } @property immutable(char[]) handle2() { i
Re: Immutable member functions and private members
On Wednesday 03 August 2011 10:37:58 simendsjo wrote: > I have a struct with a private member that is only ever accessed through > a single property method - even from within the struct. > As this property fills the value on the first access, it cannot be > immutable, and as such, none of the many methods accessing this property > can be immutable methods. > > This is according to specification, but I thought that since the single > write to the property is done at one, and only one, access point, that > it would be safe? > > I could fill this value in the constructor, but it's a bit slow, so I'd > rather do it only if needed. > > And is there any potential performance optimizations done by the > compiler, or is it "only" for safety? > Is there a way to hack around this, and more importantly, is it safe to > do so, or will I open Pandora's box? > > > Small example: > > int len(const char[] c) { > return c.length; > } > > struct S { > private immutable(char)[] _v; > @property immutable(char[]) v() { // Cannot be immutable method > if(!_v) > _v = "init"; /* or from external function */ > return _v; > } > > @property int a() { // and so this cannot be immutable method > return len(v); /* notice the property function v that might > modify _v */ > } > } > > void main() { > S s; > s.a; > } You're basically looking for logical const - albeit a subset which would be much easier to implement were we to implement it (that is, a lazy initialized const or immutable member variable). D has no support for logical const. Even worse, you're looking for logical immutable (which makes no sense at all beyond perhaps lazy initialization and probably doesn't even make sense there). The thing is that immutable methods are pointless unless you make the struct immutable (if you want to be able to call them with both a mutable and immutable instance of the struct, then you need the functions to be const, not immutable). And if you make the struct immutable, the compiler is free to put it in read-only memory if it so chooses, at which point setting _anything_ in the struct after the constructor has run is likely to blow up. So, even if you can get around the issue via casts and get both lazy initialization and immutable methods, there's a good chance that it'll blow up at some point (as in segfault or worse). If you were trying to do this with const, you might get away with it (though you'd be stepping outside of the type lsystem by casting away const and then altering anything - it's undefined behavior). But with immutable, there's no way that this is a good idea. Lazy initialization with const or immutable member variables just is _not_ a good idea in D. D provides no type-safe way to do this. You must break the type system by casting away const or immutable to even attempt it. Convievably, in the case of const, the language could be extended to allow for lazy initialization of member variables, but there's no way that it could do that with immutable (because the variable could conceivably be put in read- only memory), and even if it were done, it would likely have to be a D3 feature. Syntactically, it would probably be something like this: lazy int v = initFunc(); and then when v was first accessed, initFunc would be called and v set to that value. But that could be ugly and inefficient to implement even if it's theoretically possible, so I wouldn't bet on anything like that making it into the language. Regardless, it wouldn't be until D3. For now, D doesn't support any kind of logical const. http://stackoverflow.com/questions/4219600/logical-const-in-d - Jonathan M Davis
Immutable member functions and private members
I have a struct with a private member that is only ever accessed through a single property method - even from within the struct. As this property fills the value on the first access, it cannot be immutable, and as such, none of the many methods accessing this property can be immutable methods. This is according to specification, but I thought that since the single write to the property is done at one, and only one, access point, that it would be safe? I could fill this value in the constructor, but it's a bit slow, so I'd rather do it only if needed. And is there any potential performance optimizations done by the compiler, or is it "only" for safety? Is there a way to hack around this, and more importantly, is it safe to do so, or will I open Pandora's box? Small example: int len(const char[] c) { return c.length; } struct S { private immutable(char)[] _v; @property immutable(char[]) v() { // Cannot be immutable method if(!_v) _v = "init"; /* or from external function */ return _v; } @property int a() { // and so this cannot be immutable method return len(v); /* notice the property function v that might modify _v */ } } void main() { S s; s.a; }
Re: Convert string to wchar.
On Wednesday 03 August 2011 01:02:02 Jonathan M Davis wrote: > On Wednesday 03 August 2011 09:34:53 Pelle wrote: > > On Wed, 03 Aug 2011 08:29:09 +0200, Jacob Carlborg wrote: > > > Yes, convert the first code point to a wchar and then throw if > > > there's > > > more the one character in the string. > > > > Not tested, and I might be wrong, but 'to!' should work between dchar > > and > > wchar, no? > > > > wchar to_wchar(string s) { > > > > auto c = s.front; > > s.popFront(); > > assert (s.empty); > > return to!wchar(c); > > > > } > > It's debatable as to whether std.conv.to should be able to convert between > code units like that (you _really_ shouldn't ever be using char or wchar > outside of arrays or other ranges), but it does appear to compile, for > better or worse. It looks like the conversion works as long as the character in question will fit in the character type that you're converting to. If it doesn't fit, then it throws. So, it's as safe as such a conversion can be (though it still isn't generally a good idea to use individual chars or wchars in code). - Jonathan M Davis
Re: Convert string to wchar.
On Wednesday 03 August 2011 09:34:53 Pelle wrote: > On Wed, 03 Aug 2011 08:29:09 +0200, Jacob Carlborg wrote: > > Yes, convert the first code point to a wchar and then throw if there's > > more the one character in the string. > > Not tested, and I might be wrong, but 'to!' should work between dchar and > wchar, no? > > wchar to_wchar(string s) { > auto c = s.front; > s.popFront(); > assert (s.empty); > return to!wchar(c); > } It's debatable as to whether std.conv.to should be able to convert between code units like that (you _really_ shouldn't ever be using char or wchar outside of arrays or other ranges), but it does appear to compile, for better or worse. - Jonathan M Davis
Re: Convert string to wchar.
On Wed, 03 Aug 2011 08:29:09 +0200, Jacob Carlborg wrote: Yes, convert the first code point to a wchar and then throw if there's more the one character in the string. Not tested, and I might be wrong, but 'to!' should work between dchar and wchar, no? wchar to_wchar(string s) { auto c = s.front; s.popFront(); assert (s.empty); return to!wchar(c); }
Re: NaCl stable ABI
On 2/08/11 2:24 AM, Adam Ruppe wrote: From what I can tell, it's Google's alternative to Flash; they want to make crappy games on it. Consider that the first thing they ported to it, again, just like their javascript nonsense, was Quake. (I think Google loves Javascript too much to let it go anyway.) The API has a lot of graphics and audio stuff too which reinforces this. The games industry has been crying out for something like NaCl for a long time. It is exactly what we want: - Ability to launch games within browser without a plugin download - Platform independent ABI - No f*cking Javascript (performance will never match C++) - Safe (no need for end users to worry) JavaScript for high-quality games is a non-starter. It's too slow. You simply cannot do high performance numeric code in Javascript (http://chadaustin.me/2011/01/digging-into-javascript-performance/). Writing C++ code to run outside of the browser is a pain, and inconvenient for the user. First, you have to write your code to handle all the different platforms, which is a huge burden. Once you've done that, you need to convince users to download and install your game. It would be much more convenient to just have users go a website and be done with it. If D were usable in NaCl that would be a huge selling point for the language.