Re: %x and floats
On Thu, 24 Feb 2011 13:27:39 -0500, Trass3r wrote: > Why doesn't this work: > > import std.stdio; > void main() > { > float a,b=0; > writefln("%x %x", a, b); > } > > std.format.FormatError: std.format floating That is because %x is for formatting integers. If you want a hex representation of a floating-point number, use %a. http://www.digitalmars.com/d/2.0/phobos/std_format.html -Lars
override to!string
Hello, Imagine I have the following custom type: alias float[] Numbers; Is it possible to override to!string for Numbers so that it outputs eg like; (1.1 2.2 3.3) ? I can indeed override/specialise toImpl or formatValue for the custom type, but those overrides are simply ignored (tested). Denis -- _ vita es estrany spir.wikidot.com
implicite deref on array element access? (indexing)
Hello, I thought it worked, just like implicite deref on (struct, class) member access. But I cannot have it work: auto a = [1,2,3]; auto pa = &a; writeln((*pa)[2]); // ok writeln(pa[2]); // segfault Denis -- _ vita es estrany spir.wikidot.com
Re: rdmd problems (OS X Leopard, DMD 2.052)
On 2011-02-22 22:46:41 +0100, Paolo Invernizzi said: Hi Magnus, This is sligthly OT, but... How I loved AnyGui! Haha, cool :D Yeah, too bad the project died. Oh, well -- at least we tried :) It's nice to see you here, in the D bandwagon... Yeah, I've been looking for a more "close to the metal" language to complement Python for a looong time (using C and C++ when I had to -- and sometimes Java or Cython and what-have-you). At the moment I'm hopeful that D might be what I've been looking for. Loving it so far :) (Still using Python, though. Just came out with a new Python book, "Python Algorithms", last fall ;) -- Magnus Lie Hetland http://hetland.org
Re: implicite deref on array element access? (indexing)
This should explain everything: auto a = [1,2,3]; auto pa = &a; writeln(&pa); writeln(&pa+1); Do the math!
Re: override to!string
spir Wrote: > Hello, > > Imagine I have the following custom type: > alias float[] Numbers; > > Is it possible to override to!string for Numbers so that it outputs eg like; > (1.1 2.2 3.3) > ? No, this is one reason for writeTo replacing toString, or whatever the name. It would allow a formatter specified. I don't really know how to! would be changed to fit into that. > I can indeed override/specialise toImpl or formatValue for the custom type, > but > those overrides are simply ignored (tested). Right, that would be anti-hijacking at work. Don't want behavior changed because you imported a module. You might be able to override to itself though. Otherwise you can use format specifiers from std.string.format.
Re: implicite deref on array element access? (indexing)
Actually that doesn't explain anything! What I mean is, arrays in D are not the same as arrays in C. auto a = [1, 2, 3]; auto pa = &a; writeln(&a[0]); writeln(&a[1]); writeln(&a[2]); writeln(&pa[0]); writeln(&pa[1]); writeln(&pa[2]); 9A2E40 9A2E44 9A2E48 12FE34 12FE3C 12FE44 Afaik D arrays have a length and then a pointer to the contents of the array (someone correct me on this if I'm wrong?).
Re: rdmd problems (OS X Leopard, DMD 2.052)
On 2011-02-21 15:17:44 +0100, Jacob Carlborg said: On 2011-02-21 14:16, Lars T. Kyllingstad wrote: Say you have a file "myscript", that starts with the line #!/path/to/interpreter --foo --bar If you run this as ./myscript --hello --world then the args[] received by the interpreter program looks like this: args[0] = "/path/to/interpreter" args[1] = "--foo --bar" args[2] = "./myscript" args[3] = "--hello" args[4] = "--world" This is the case on every shell I've tried on Linux, at least. Let me first clarify: By "nothing happens", I really mean that. When I supply --shebang, the code isn't compiled, and nothing is run. Running the script becomes a no-op. As for your example: The switches to rdmd *don't* appear in args for me. So for example, if I have #!/path/to/rdmd -unittest ... as the shebang line, rdmd finds and passes the -unittest switch to dmd (my unit tests work). I get no problems when I add more switches either (i.e., rdmd doesn't complain). But, as far as I can see, none of these end up in args. (Or are we talking about different things here?) Instead, args[0] contains the full path to the temporary executable built and run by rdmd, and args[1..$] contain any arguments I supplied when running the script. The fact that --shebang borks the whole execution seems like it must be a bug. As for the rest of the behavior, it seems pretty useful to me, but perhaps OS X-specific? (That would be odd, but who knows...) -- Magnus Lie Hetland http://hetland.org
Re: implicite deref on array element access? (indexing)
P.S. I got bitten by this when I was interfacing with C. Only in my case I used multidimensional arrays. I just assumed they were the same thing as in C, but I was wrong.
How do you test pre-/post-conditions and invariants?
Or, more generally, how do you test asserts (which is what I'm using in my preconditions etc.)? As far as I can see, collectException() won't collect errors, which is what assert() throws -- so what's the standard way of writing unit tests for preconditions that use assert? (I.e., test that they will, in fact, throw when you break them.) -- Magnus Lie Hetland http://hetland.org
Re: implicite deref on array element access? (indexing)
spir Wrote: > Hello, > > I thought it worked, just like implicite deref on (struct, class) member > access. But I cannot have it work: > > auto a = [1,2,3]; > auto pa = &a; > writeln((*pa)[2]); // ok > writeln(pa[2]); // segfault You aren't making a pointer to the data, only the array. I probably would have made the same mistake, but I think you want to use: auto pa = a.ptr; Don't know if there is a ptr property for array.
Re: implicite deref on array element access? (indexing)
On Fri, 25 Feb 2011 10:15:52 -0500, spir wrote: Hello, I thought it worked, just like implicite deref on (struct, class) member access. But I cannot have it work: auto a = [1,2,3]; auto pa = &a; writeln((*pa)[2]); // ok writeln(pa[2]); // segfault Because indexing a pointer like ptr[n] is the equivalent of *(ptr + n). This is how it is in C. Fun fact, you can avoid array bounds checks (if you know the index is valid) by doing arr.ptr[n] -Steve
Re: implicite deref on array element access? (indexing)
On 2/25/11, Steven Schveighoffer wrote: > Fun fact, you can avoid array bounds checks (if you know the index is > valid) by doing arr.ptr[n] Can't you do the same with -noboundscheck ?
Re: implicite deref on array element access? (indexing)
On Fri, 25 Feb 2011 10:58:49 -0500, Andrej Mitrovic wrote: On 2/25/11, Steven Schveighoffer wrote: Fun fact, you can avoid array bounds checks (if you know the index is valid) by doing arr.ptr[n] Can't you do the same with -noboundscheck ? No, -noboundscheck stops bounds checking everywhere. arr.ptr[n] stops bounds checking for that one statement. It's a lot easier to prove that one time that bounds checking is not necessary than it is to prove that no bounds checking is necessary anywhere. Plus, you can't always control the command line. -Steve
Re: override to!string
On 25.02.2011 17:28, spir wrote: Hello, Imagine I have the following custom type: alias float[] Numbers; Is it possible to override to!string for Numbers so that it outputs eg like; (1.1 2.2 3.3) ? I can indeed override/specialise toImpl or formatValue for the custom type, but those overrides are simply ignored (tested). Denis First things first, it's just an alias and not a custom type. So compiler won't distinguish between float[] and Numbers at all. The obvious way around is make your own thin wrapper, but yeah, it won't get format specifiers until writeTo or similar proposal implemented. import std.stdio,std.conv; struct Numbers{ float[] data; string toString(){ string result = "("; foreach(val;data[0..$-1]){ result ~= to!string(val); result ~= ' '; } result ~= to!string(data[$-1]); result ~= ')'; return result; } alias data this; } Usage: void main(){ Numbers nums = Numbers([1.1,2.2,3.3]); writefln("%s",nums); nums[0] = 4.4; writefln("%s",nums); } -- Dmitry Olshansky
Re: How do you test pre-/post-conditions and invariants?
On 02/25/2011 04:30 PM, Magnus Lie Hetland wrote: Or, more generally, how do you test asserts (which is what I'm using in my preconditions etc.)? As far as I can see, collectException() won't collect errors, which is what assert() throws -- so what's the standard way of writing unit tests for preconditions that use assert? (I.e., test that they will, in fact, throw when you break them.) See the page on DbC: http://www.digitalmars.com/d/2.0/dbc.html. Denis -- _ vita es estrany spir.wikidot.com
Re: implicite deref on array element access? (indexing)
On 02/25/2011 04:43 PM, Steven Schveighoffer wrote: On Fri, 25 Feb 2011 10:15:52 -0500, spir wrote: Hello, I thought it worked, just like implicite deref on (struct, class) member access. But I cannot have it work: auto a = [1,2,3]; auto pa = &a; writeln((*pa)[2]); // ok writeln(pa[2]); // segfault Because indexing a pointer like ptr[n] is the equivalent of *(ptr + n). This is how it is in C. Fun fact, you can avoid array bounds checks (if you know the index is valid) by doing arr.ptr[n] All right! This is what I did not get. Thank you, Steve. Too bad. Anyway, in the meanwhile I have opted for another approach. (FWIW, in Oberon implicite deref works on array indexing just like on struct [record] member access.) Denis -- _ vita es estrany spir.wikidot.com
Re: How do you test pre-/post-conditions and invariants?
On 2/25/11 1:48 PM, spir wrote: On 02/25/2011 04:30 PM, Magnus Lie Hetland wrote: Or, more generally, how do you test asserts (which is what I'm using in my preconditions etc.)? As far as I can see, collectException() won't collect errors, which is what assert() throws -- so what's the standard way of writing unit tests for preconditions that use assert? (I.e., test that they will, in fact, throw when you break them.) See the page on DbC: http://www.digitalmars.com/d/2.0/dbc.html. Denis By the way, the link to "Adding Contracts to Java" at the bottom of the page is broken.
Re: How do you test pre-/post-conditions and invariants?
Magnus Lie Hetland Wrote: > Or, more generally, how do you test asserts (which is what I'm using in > my preconditions etc.)? > > As far as I can see, collectException() won't collect errors, which is > what assert() throws -- so what's the standard way of writing unit > tests for preconditions that use assert? (I.e., test that they will, in > fact, throw when you break them.) There has been talk of a std.unittest that would help with this, but for now: unittest { try { callMeWrong(wrong); assert(0); catch(AssertError e) { } } }
Foreach with byte problems
So I'd like to print all values storable in a byte in hex representation: import std.stdio; void main() { int counter; foreach (byte index; byte.min..byte.max) { if (!(counter % 4)) writeln(); writef("%#.2x, ", index); counter++; } } If you run this, you'll realize that it doesn't print the final 0x7F. This is because in a foreach range literal (is that the correct term?), the left side is inclusive, but the right side isn't. Hence this will run the foreach from 0 to 9: foreach (index; 0..10) { } So I figured I'd just add a +1 at the end, but then I get an error: foreach (byte index; byte.min..byte.max+1) { } Error: cannot implicitly convert expression (128) of type int to byte. Of course 128 can't fit in a byte. But how am I supposed to print out the last value if the right hand side of a range literal is non-inclusive? This behavior is kind of odd, don't you think? byte.max is 127, but due to the way foreach works, the last value assigned to index is 126. If I was allowed to add +1 for RHS, the last value stored to index would be 127 due to the non-inclusive right side, which is completely legal. Yet DMD complains that I'm trying to store 128 to index. I guess DMD first checks if the value on the RHS of the range literal can fit to a byte before it cuts one off due to the way range literals work. So how do I work around this?
Re: Foreach with byte problems
On Fri, 25 Feb 2011 13:52:53 -0500, Andrej Mitrovic wrote: So I'd like to print all values storable in a byte in hex representation: import std.stdio; void main() { int counter; foreach (byte index; byte.min..byte.max) { if (!(counter % 4)) writeln(); writef("%#.2x, ", index); counter++; } } If you run this, you'll realize that it doesn't print the final 0x7F. This is because in a foreach range literal (is that the correct term?), the left side is inclusive, but the right side isn't. Hence this will run the foreach from 0 to 9: foreach (index; 0..10) { } So I figured I'd just add a +1 at the end, but then I get an error: foreach (byte index; byte.min..byte.max+1) { } Error: cannot implicitly convert expression (128) of type int to byte. Of course 128 can't fit in a byte. But how am I supposed to print out the last value if the right hand side of a range literal is non-inclusive? foreach(int index; byte.min..byte.max + 1) The truth is, you don't want to use byte to represent your comparisons, because byte.max + 1 isn't a valid byte. And instead of counter, you can use a formula instead: if((index - byte.min) % 4 == 0) writeln(); -Steve
Re: How do you test pre-/post-conditions and invariants?
On Friday, February 25, 2011 07:30:50 Magnus Lie Hetland wrote: > Or, more generally, how do you test asserts (which is what I'm using in > my preconditions etc.)? > > As far as I can see, collectException() won't collect errors, which is > what assert() throws -- so what's the standard way of writing unit > tests for preconditions that use assert? (I.e., test that they will, in > fact, throw when you break them.) I think that the reality of the matter is the most of the time people _don't_ check them. And on some level, it doesn't make sense to. It's kind of like asking how people test their unit tests. Unit tests are already testing code. Do you want to be testing them on top of that? And if you do, do you test _that_ code? Where do you stop? Pre-conditions, post-conditions, and invariants are testing the class or struct that they're on, and to some extent, the code that uses them. So, if you're looking to test them, you're looking to test test code. And testing post-conditions and invariants in the manner that you're trying to do borders on impossible. What are you going to do, repeat the post-condition or invariant test on the result of the function or on the state of the object that the function was called on after the function was called? That's just doing the test twice. You might as well just re-read the post-conditions and invariants to make sure that you wrote them correctly. I do see value in testing pre-conditions if you're using exceptions rather than assertions (which means that you're not use in blocks). In that case, you're testing the API to make sure that it does what it's supposed to do. But if you're dealing with assertions, then it's really test code as opposed to API code, and I don't see the same value in testing that. You'd just be testing test code. Now, assuming that you _do_ want to test that sort of thing (as you obviously want to), some new unit testing functions which would help were recently reviewed on the D newsgroup and voted for inclusion in Phobos. There's a pull request for them, but they haven't been merged in yet, and unless you use the development version of Phobos from git, you'll have to wait for the next release regardless. Those changes _do_ make it so that you can use collectException to collect an Error (though it defaults to catching Exceptions only), but they also include assertThrown and assertNotThrown which effectively assert that the Exception or Error that you expected to be thrown (or not) from a particular expression or function call was indeed thrown (or not). So, you _can_ use that with AssertError to verify your pre-conditions. However, I would point out that catching Errors is generally a _bad_ idea. If you're careful in unit testing code, you should be okay, but _don't_ do it in normal code, and if you're not careful, you'll still get into trouble with unit testing code. Unlike with Exceptions, when an Error is thrown, scope statements and finally blocks do not run. I don't believe that destructors are run either. It's pretty much assumed that you can't recover from an Error, so no attempt to recover is made. Your program runs a high risk of being in an invalid state after an Error is thrown - AssertError included. In a unit test, if you're dealing with simple stuff, then you're probably okay, but if you have any code in there that would be affected by scope statements, finally blocks, destructors, etc. not running, then you don't want to be catching any Errors and then trying to continue. So, functions which will help you with such testing are on their way, but they weren't released with the latest release of dmd, and once they have been released, you're going to need to be careful if you use them to test AssertErrors or any other kind of Error. - Jonathan M Davis
Re: Foreach with byte problems
Maybe it's best to let D do type infering for me. This works ok: foreach (index; byte.min..byte.max+1) { if((index - byte.min) % 4 == 0) writeln(); writef("%#.2x, ", index); } I'm fine with that. Now, what's wrong with this code: auto foo = iota(byte.min, byte.max-1); // ok // foo = [0, 1, .., 124, 125] auto bar = iota(byte.min, byte.max); // fails // Errors: // D:\DMD\dmd2\windows\bin\..\..\src\phobos\std\range.d(3868): Error: cannot implicitly convert expression (cast(int)pastLast - 1) of type int to byte // D:\DMD\dmd2\windows\bin\..\..\src\phobos\std\range.d(3873): Error: cannot implicitly convert expression (cast(int)pastLast + 1) of type int to byte // D:\DMD\dmd2\windows\bin\..\..\src\phobos\std\range.d(3890): Error: cannot implicitly convert expression (cast(uint)cast(int)this.pastLast - this.step) of type uint to byte
array idioms
Hello, What's the idiomatic way to: * delete an element in an associative array * delete an element in a dyn array * insert an element in a dyn array Thank you, Denis -- _ vita es estrany spir.wikidot.com
Re: Foreach with byte problems
Can this be simplified?: byte[] arr = to!(byte[])(array(iota(byte.min, byte.max+1))); The +1 turns byte.max into an int that can store 128. So when I call array on an iota, I'll get back an int[] of [-128, ..., 127]. And I have to convert that to a byte[].
Re: Foreach with byte problems
On 02/25/2011 07:52 PM, Andrej Mitrovic wrote: So I'd like to print all values storable in a byte in hex representation: import std.stdio; void main() { int counter; foreach (byte index; byte.min..byte.max) { if (!(counter % 4)) writeln(); writef("%#.2x, ", index); counter++; } } If you run this, you'll realize that it doesn't print the final 0x7F. This is because in a foreach range literal (is that the correct term?), the left side is inclusive, but the right side isn't. Hence this will run the foreach from 0 to 9: foreach (index; 0..10) { } So I figured I'd just add a +1 at the end, but then I get an error: foreach (byte index; byte.min..byte.max+1) { } Error: cannot implicitly convert expression (128) of type int to byte. Of course 128 can't fit in a byte. But how am I supposed to print out the last value if the right hand side of a range literal is non-inclusive? This behavior is kind of odd, don't you think? byte.max is 127, but due to the way foreach works, the last value assigned to index is 126. If I was allowed to add +1 for RHS, the last value stored to index would be 127 due to the non-inclusive right side, which is completely legal. Yet DMD complains that I'm trying to store 128 to index. I guess DMD first checks if the value on the RHS of the range literal can fit to a byte before it cuts one off due to the way range literals work. So how do I work around this? lol! One more source of fun in using half-open intervals :-) Denis -- _ vita es estrany spir.wikidot.com
Re: Foreach with byte problems
On Fri, 25 Feb 2011 14:15:52 -0500, Andrej Mitrovic wrote: Maybe it's best to let D do type infering for me. This works ok: foreach (index; byte.min..byte.max+1) { if((index - byte.min) % 4 == 0) writeln(); writef("%#.2x, ", index); } I'm fine with that. Now, what's wrong with this code: auto foo = iota(byte.min, byte.max-1); // ok // foo = [0, 1, .., 124, 125] auto bar = iota(byte.min, byte.max); // fails // Errors: // D:\DMD\dmd2\windows\bin\..\..\src\phobos\std\range.d(3868): Error: cannot implicitly convert expression (cast(int)pastLast - 1) of type int to byte // D:\DMD\dmd2\windows\bin\..\..\src\phobos\std\range.d(3873): Error: cannot implicitly convert expression (cast(int)pastLast + 1) of type int to byte // D:\DMD\dmd2\windows\bin\..\..\src\phobos\std\range.d(3890): Error: cannot implicitly convert expression (cast(uint)cast(int)this.pastLast - this.step) of type uint to byte IFTI is interpreting the element type of iota to byte. You need to either explicitly instantiate iota (don't recommend this) or cast one of your args to int. auto bar = iota(cast(int)byte.min, byte.max); a dirty trick you could do is add 0, which should promote the arg to int. -Steve
Re: Foreach with byte problems
On Fri, 25 Feb 2011 14:34:35 -0500, Andrej Mitrovic wrote: Can this be simplified?: byte[] arr = to!(byte[])(array(iota(byte.min, byte.max+1))); The +1 turns byte.max into an int that can store 128. So when I call array on an iota, I'll get back an int[] of [-128, ..., 127]. And I have to convert that to a byte[]. This is a good puzzle. You may have to do something with map and casting, but I don't see how it can be done with iota without a cast. The right thing to do would be this: for(byte i = -127; i < byte.max + 1; i++) arr ~= i; which does everything as a byte, but does the comparisons as ints. But I don't know how to make iota do this. -Steve
Re: Foreach with byte problems
On 2/25/11, Steven Schveighoffer wrote: > a dirty trick you could do is add 0, which should promote the arg to int. Cool. I've almost used +1-1, LOL! Well, I thought DMD would simply ignore +0 (dead code elimination?), but apparently this is a cool shorthand for casting literals? Nice.
Re: array idioms
On 2/25/11, spir wrote: > * delete an element in an associative array Just use .remove? void main() { auto var = ["a" : 1]; var.remove("b");// nothing happens var.remove("a");// "a" key is gone assert(!var.length); // empty }
Re: array idioms
On Friday, February 25, 2011 11:30:28 spir wrote: > Hello, > > What's the idiomatic way to: > > * delete an element in an associative array If you have the key, then just use remove. The online documentation for asseciative array discusses it. e.g. b.remove("hello"); If you're looking to remove by value, however, you're going to have to figure out what its key is. And if you want to remove _all_ elements with the same value, then you're going to need to find _all_ of their keys. The best way to do that would probably just be to use a foreach loop: foreach(k, v; aa) { if(v == value) aa.remove(k); } I'm not sure if there are any problems with removing from an associative array while iterating over it though. I wouldn't think so, but I don't know so. Worst case though, you save the list of keys to remove and then remove them all once you have them all. > * delete an element in a dyn array I don't think that there is one right now. There should probably be a function in std.array which does what remove in std.container would do, but I don't believe that there's a function for it right now. So, the simplest way at the moment (albeit not the most efficient) would probably do to something like auto found = findSplit(arr, value); auto newArr = array(chain(found[0], found[2])); The efficient way to do it, however, would involve shifting all of the elements in the array, which is more complicated and not the kind of code that you really want to be rewriting every time that you need to remove an element. But you _do_ need to remember that removing an arbitrary element from an array is _not_ cheap, because even in the most efficient case, that means moving a potentially large number of elements in the array - unlike a linked list where removal is cheap. Of course, popFront and popBack would be the best way to remove from the ends of an array, and _that_ is efficient. > * insert an element in a dyn array Same as remove. There's no function for doing it at the moment. The best way at present would probably be to just concatenate the slices. auto newArr = arr[0 .. i] ~ [value] ~ [i .. $]; But again, that's not particularly efficient. What you'd really want to do would be increase the size of the array by one, shift all of the elements after the insertion point over by one, and then set the element at the insertion point to the value that you're inserting. And of course, if appending to the array, ~= would be the best way to do it. And again, inserting into arrays is _not_ efficient regardless, so if you're doing that sort of thing a lot, you probably should be using a different type of container. - Jonathan M Davis
Re: Foreach with byte problems
On Fri, 25 Feb 2011 14:51:18 -0500, Andrej Mitrovic wrote: On 2/25/11, Steven Schveighoffer wrote: a dirty trick you could do is add 0, which should promote the arg to int. Cool. I've almost used +1-1, LOL! Well, I thought DMD would simply ignore +0 (dead code elimination?), but apparently this is a cool shorthand for casting literals? Nice. No code is generated to add 0, but it does affect the type. -Steve
Re: std.xml empty element
El 24/02/2011 19:40, Tom escribió: El 24/02/2011 09:51, Jacob Carlborg escribió: On 2011-02-24 06:48, Tom wrote: Hi, how can I create an empty element with current D2 std.xml Element implementation? stdout.writeln(new Element("foo")); // Shields instead of Thanks in advance, Tom; http://d.puremagic.com/issues/show_bug.cgi?id=4394 I see :( Thanks... Lucky me, 2.052 solves this bug and doesn't break anything. Tom;
Re: array idioms
On Fri, 25 Feb 2011 15:09:44 -0500, Jonathan M Davis wrote: On Friday, February 25, 2011 11:30:28 spir wrote: Hello, What's the idiomatic way to: * delete an element in an associative array If you have the key, then just use remove. The online documentation for asseciative array discusses it. e.g. b.remove("hello"); If you're looking to remove by value, however, you're going to have to figure out what its key is. And if you want to remove _all_ elements with the same value, then you're going to need to find _all_ of their keys. The best way to do that would probably just be to use a foreach loop: foreach(k, v; aa) { if(v == value) aa.remove(k); } I'm not sure if there are any problems with removing from an associative array while iterating over it though. I wouldn't think so, but I don't know so. Worst case though, you save the list of keys to remove and then remove them all once you have them all. It is illegal to remove from an AA you are iterating. I've learned first hand that this causes subtle memory bugs. Do not do this. However, dcollections supports this idiom via the purge operation: foreach(ref doPurge, v; &mymap.purge) doPurge = (v == value); -Steve
Re: array idioms
On 2/25/11, Jonathan M Davis wrote: > >> * insert an element in a dyn array > > Same as remove. There's no function for doing it at the moment. std.array.insert: int[] a = [ 1, 2, 3, 4 ]; a.insert(2, [ 1, 2 ]); assert(a == [ 1, 2, 1, 2, 3, 4 ]); afaik insert was missing from the documentation in the last release (I've reported it), but now it's back in. So maybe that's why nobody knew about it.
Re: array idioms
On Friday 25 February 2011 12:16:19 Steven Schveighoffer wrote: > On Fri, 25 Feb 2011 15:09:44 -0500, Jonathan M Davis > > wrote: > > On Friday, February 25, 2011 11:30:28 spir wrote: > >> Hello, > >> > >> What's the idiomatic way to: > >> > >> * delete an element in an associative array > > > > If you have the key, then just use remove. The online documentation for > > asseciative array discusses it. e.g. > > > > b.remove("hello"); > > > > If you're looking to remove by value, however, you're going to have to > > figure out > > what its key is. And if you want to remove _all_ elements with the same > > value, > > then you're going to need to find _all_ of their keys. The best way to > > do that > > would probably just be to use a foreach loop: > > > > foreach(k, v; aa) > > { > > > > if(v == value) > > > > aa.remove(k); > > > > } > > > > I'm not sure if there are any problems with removing from an associative > > array > > while iterating over it though. I wouldn't think so, but I don't know > > so. Worst > > case though, you save the list of keys to remove and then remove them > > all once > > you have them all. > > It is illegal to remove from an AA you are iterating. I've learned first > hand that this causes subtle memory bugs. Do not do this. Good to know. I was wondering. It's simple enough though to just make a list of the keys to remove and then remove them afterwords. - Jonathan M Davis
Re: array idioms
On Friday 25 February 2011 12:09:44 Jonathan M Davis wrote: > On Friday, February 25, 2011 11:30:28 spir wrote: > > * delete an element in a dyn array > > I don't think that there is one right now. There should probably be a > function in std.array which does what remove in std.container would do, > but I don't believe that there's a function for it right now. So, the > simplest way at the moment (albeit not the most efficient) would probably > do to something like > > auto found = findSplit(arr, value); > auto newArr = array(chain(found[0], found[2])); > > The efficient way to do it, however, would involve shifting all of the > elements in the array, which is more complicated and not the kind of code > that you really want to be rewriting every time that you need to remove an > element. But you _do_ need to remember that removing an arbitrary element > from an array is _not_ cheap, because even in the most efficient case, > that means moving a potentially large number of elements in the array - > unlike a linked list where removal is cheap. > > Of course, popFront and popBack would be the best way to remove from the > ends of an array, and _that_ is efficient. Actually, on reflection, we probably _don't_ want a remove like std.container uses. What we probably want is something like remove and removeInPlace. The fact that dynamic arrays are really ranges rather than containers makes removing in place _far_ less desirable in many cases, and it's not necessarily a good idea to treat an array like a container in std.container. - Jonathan M Davis
Re: array idioms
On Friday 25 February 2011 12:30:00 Andrej Mitrovic wrote: > On 2/25/11, Jonathan M Davis wrote: > >> * insert an element in a dyn array > > > > Same as remove. There's no function for doing it at the moment. > > std.array.insert: > > int[] a = [ 1, 2, 3, 4 ]; > a.insert(2, [ 1, 2 ]); > assert(a == [ 1, 2, 1, 2, 3, 4 ]); > > afaik insert was missing from the documentation in the last release > (I've reported it), but now it's back in. So maybe that's why nobody > knew about it. Ah. Good to know. Its not the sort of thing that I'm generally looking to do, however, so I don't tend to think about it. I don't believe that I've ever seen the function in the docs before, so that would explain why didn't know about it. - Jonathan M Davis
Re: array idioms
I have asked for remove before, I got some responses here (in fact, Jonathan made an enhancement request for it): http://www.digitalmars.com/d/archives/digitalmars/D/learn/Removing_an_object_from_a_range_23212.html The topic was derailed, but essentially you can provide a predicate as a function literal to do the work: import std.stdio; import std.algorithm; void main() { int[] elements = [1, 2, 3, 2, 4]; int needle = 2; elements = remove!((item) {return item == needle;} )(elements); assert(elements == [1, 3, 4]); }
Re: array idioms
On Friday, February 25, 2011 12:51:53 Andrej Mitrovic wrote: > I have asked for remove before, I got some responses here (in fact, > Jonathan made an enhancement request for it): > > http://www.digitalmars.com/d/archives/digitalmars/D/learn/Removing_an_objec > t_from_a_range_23212.html > > The topic was derailed, but essentially you can provide a predicate as > a function literal to do the work: > > import std.stdio; > import std.algorithm; > > void main() > { > int[] elements = [1, 2, 3, 2, 4]; > int needle = 2; > > elements = remove!((item) {return item == needle;} )(elements); > assert(elements == [1, 3, 4]); > } Actually, you can probably just use replace and give it an empty range for the third argument. Still, there should probably be a function in std.array which removes a value from an array based on its value. A function that's essentially identical to the version of replace which takes two ranges in addition to the array but doesn't take the range to replace with would probably do the trick: R1 replace(R1, R2)(R1 subject, R2 toRemove) if(...) {...} - Jonathan M Davis
Re: Foreach with byte problems
On Friday, February 25, 2011 11:37:23 spir wrote: > On 02/25/2011 07:52 PM, Andrej Mitrovic wrote: > > So I'd like to print all values storable in a byte in hex representation: > > > > import std.stdio; > > void main() > > { > > > > int counter; > > foreach (byte index; byte.min..byte.max) > > { > > > > if (!(counter % 4)) > > > > writeln(); > > > > writef("%#.2x, ", index); > > counter++; > > > > } > > > > } > > > > If you run this, you'll realize that it doesn't print the final 0x7F. > > This is because in a foreach range literal (is that the correct term?), > > the left side is inclusive, but the right side isn't. > > > > Hence this will run the foreach from 0 to 9: > > foreach (index; 0..10) { } > > > > So I figured I'd just add a +1 at the end, but then I get an error: > > foreach (byte index; byte.min..byte.max+1) > > { > > } > > > > Error: cannot implicitly convert expression (128) of type int to > > byte. > > > > Of course 128 can't fit in a byte. But how am I supposed to print out the > > last value if the right hand side of a range literal is non-inclusive? > > > > This behavior is kind of odd, don't you think? > > > > byte.max is 127, but due to the way foreach works, the last value > > assigned to index is 126. If I was allowed to add +1 for RHS, the last > > value stored to index would be 127 due to the non-inclusive right side, > > which is completely legal. Yet DMD complains that I'm trying to store > > 128 to index. > > > > I guess DMD first checks if the value on the RHS of the range literal can > > fit to a byte before it cuts one off due to the way range literals work. > > So how do I work around this? > > lol! One more source of fun in using half-open intervals :-) In the general case, having the first element of an interval be inclusive and the last one exclusive is perfect. That's how it works with iterators in C++. That's essentially how it works with array indices, since they start with 0 and their length is one greater than the last index. It's just plain nice and makes checking end conditions cleaner. However, it is true that in this particular case, it's annoying. Still, in the general case, I do believe that it's definitely the right behavior. - Jonathan M Davis
Re: Foreach with byte problems
On 2/25/11, Jonathan M Davis wrote: > However, it is true that in this particular case, it's annoying. Still, in > the > general case, I do believe that it's definitely the right behavior. > > - Jonathan M Davis > I do agree it's the right thing to do, and I wouldn't want to change it. But I'd like the compiler to be smart in this case and see that there's no way 128 will ever be stored into a byte. It's not some crucial piece of code that I need working. I just ran into it by accident really.
Re: array idioms
On 02/25/2011 08:55 PM, Andrej Mitrovic wrote: On 2/25/11, spir wrote: * delete an element in an associative array Just use .remove? void main() { auto var = ["a" : 1]; var.remove("b");// nothing happens var.remove("a");// "a" key is gone assert(!var.length); // empty } Sh*t, I have missed it. Sorry for the no*se. But where is this func implemented? I could not find it by browsing. (It's also not in object.d, apparently; while usually when I cannot find something, it's hidden in there ;-) Denis -- _ vita es estrany spir.wikidot.com
Re: Foreach with byte problems
On 02/25/2011 10:52 AM, Andrej Mitrovic wrote: So I'd like to print all values storable in a byte in hex representation: import std.stdio; void main() { int counter; foreach (byte index; byte.min..byte.max) { if (!(counter % 4)) writeln(); writef("%#.2x, ", index); counter++; } } If you run this, you'll realize that it doesn't print the final 0x7F. This is because in a foreach range literal (is that the correct term?), the left side is inclusive, but the right side isn't. I've seen the same "problem" with enums. import std.stdio; enum E { x, y, z } void main() { foreach (e; E.min .. E.max) { writeln(e); } } The value 2 is excluded. Of course it's rare to use enums like that in a foreach loop as their values are not always continuous. I found out the better solution before sending this message: foreach (e; __traits(allMembers, E)) { writeln(e); } The difference is, the type of 'e' is string above. Finally, the following produces integer values: foreach (e; __traits(allMembers, E)) { writeln(to!E(e)); } Ok, good... :) Ali
Re: How do you test pre-/post-conditions and invariants?
On 2011-02-25 19:18:40 +0100, Jesse Phillips said: There has been talk of a std.unittest that would help with this, but for now: unittest { try { callMeWrong(wrong); assert(0); catch(AssertError e) { } } } Ah. I used something like... auto thrown = 0; try foo() catch (AssertError) thrown++; ... assert(thrown == k); I guess I could wrap it up a bit, or something. -- Magnus Lie Hetland http://hetland.org
Re: How do you test pre-/post-conditions and invariants?
On 2011-02-25 17:48:54 +0100, spir said: On 02/25/2011 04:30 PM, Magnus Lie Hetland wrote: Or, more generally, how do you test asserts (which is what I'm using in my preconditions etc.)? As far as I can see, collectException() won't collect errors, which is what assert() throws -- so what's the standard way of writing unit tests for preconditions that use assert? (I.e., test that they will, in fact, throw when you break them.) See the page on DbC: http://www.digitalmars.com/d/2.0/dbc.html. Denis Hm. I'm not sure how this answers my question. I know how pre/postconditions etc. work -- I was asking for how to test them in a unit test (i.e., ensure that they'll kick in if you provide faulty intput, for example). Maybe I'm missing something in the doc you referred me to? -- Magnus Lie Hetland http://hetland.org
Re: array idioms
On 2/25/11, spir wrote: > But where is this func > implemented? DMD\dmd2\src\druntime\src\rt\aaA.d _aaDel && _aaDelX And then in object.d: extern (C) { // from druntime/src/compiler/dmd/aaA.d ... void _aaDel(void* p, TypeInfo keyti, ...); ... } I don't really know how it gets called since I don't see any explicit calls to this function. This probably requires more insight into how druntime and dmd work together.
Re: How do you test pre-/post-conditions and invariants?
On 2011-02-25 20:04:10 +0100, Jonathan M Davis said: On Friday, February 25, 2011 07:30:50 Magnus Lie Hetland wrote: Or, more generally, how do you test asserts (which is what I'm using in my preconditions etc.)? As far as I can see, collectException() won't collect errors, which is what assert() throws -- so what's the standard way of writing unit tests for preconditions that use assert? (I.e., test that they will, in fact, throw when you break them.) I think that the reality of the matter is the most of the time people _don't_ check them. And on some level, it doesn't make sense to. It's kind of like asking how people test their unit tests. Unit tests are already testing code. Do you want to be testing them on top of that? And if you do, do you test _that_ code? Where do you stop? I guess so. But you could say the same thing about other cases where you throw an exception when you detect that something is wrong -- but those are normally tested, right? Also, the difference here is that the precondition is written as a general "test", whereas my actual test would have specific cases. For example, I have a test that checks that I don't add the same object twice to some structure, and the check involves some traversal -- code that could potentially be wrong. I wanted to make sure that it wasn't by explicitly adding the same object twice -- code (i.e., my unit test) that most likely could not be wrong. But I do see your point. [snip] And testing post-conditions and invariants in the manner that you're trying to do borders on impossible. What are you going to do, repeat the post-condition or invariant test on the result of the function or on the state of the object that the function was called on after the function was called? That's just doing the test twice. Right. You might as well just re-read the post-conditions and invariants to make sure that you wrote them correctly. I do see value in testing pre-conditions if you're using exceptions rather than assertions (which means that you're not use in blocks). In that case, you're testing the API to make sure that it does what it's supposed to do. But if you're dealing with assertions, then it's really test code as opposed to API code, and I don't see the same value in testing that. You'd just be testing test code. OK. For the practical reason, I refer you to my explanation above. But I guess it's a style issue -- and I'm fine with not testing these things, by all means. [snip] Those changes _do_ make it so that you can use collectException to collect an Error (though it defaults to catching Exceptions only), but they also include assertThrown and assertNotThrown which effectively assert that the Exception or Error that you expected to be thrown (or not) from a particular expression or function call was indeed thrown (or not). So, you _can_ use that with AssertError to verify your pre-conditions. OK, thanks. However, I would point out that catching Errors is generally a _bad_ idea. [snip lots of useful stuff] Thanks for educating me :D I guess the conclusion will be that I'll focus on keeping my preconditions really simple. (And any utility functions I use in them can then get unit tests of their own instead ;) -- Magnus Lie Hetland http://hetland.org
Re: array idioms
On 02/25/2011 09:09 PM, Jonathan M Davis wrote: On Friday, February 25, 2011 11:30:28 spir wrote: Hello, What's the idiomatic way to: * delete an element in an associative array If you have the key, then just use remove. The online documentation for asseciative array discusses it. e.g. b.remove("hello"); If you're looking to remove by value, however, you're going to have to figure out what its key is. And if you want to remove _all_ elements with the same value, then you're going to need to find _all_ of their keys. The best way to do that would probably just be to use a foreach loop: foreach(k, v; aa) { if(v == value) aa.remove(k); } I'm not sure if there are any problems with removing from an associative array while iterating over it though. I wouldn't think so, but I don't know so. Worst case though, you save the list of keys to remove and then remove them all once you have them all. * delete an element in a dyn array I don't think that there is one right now. There should probably be a function in std.array which does what remove in std.container would do, but I don't believe that there's a function for it right now. So, the simplest way at the moment (albeit not the most efficient) would probably do to something like auto found = findSplit(arr, value); auto newArr = array(chain(found[0], found[2])); The efficient way to do it, however, would involve shifting all of the elements in the array, which is more complicated and not the kind of code that you really want to be rewriting every time that you need to remove an element. But you _do_ need to remember that removing an arbitrary element from an array is _not_ cheap, because even in the most efficient case, that means moving a potentially large number of elements in the array - unlike a linked list where removal is cheap. Of course, popFront and popBack would be the best way to remove from the ends of an array, and _that_ is efficient. * insert an element in a dyn array Same as remove. There's no function for doing it at the moment. The best way at present would probably be to just concatenate the slices. auto newArr = arr[0 .. i] ~ [value] ~ [i .. $]; But again, that's not particularly efficient. What you'd really want to do would be increase the size of the array by one, shift all of the elements after the insertion point over by one, and then set the element at the insertion point to the value that you're inserting. And of course, if appending to the array, ~= would be the best way to do it. And again, inserting into arrays is _not_ efficient regardless, so if you're doing that sort of thing a lot, you probably should be using a different type of container. Thank you very much Jonathan. That's what I was afraid of (and why I asked): there is no builtin func for those operations because they cannot by simple & cheap. The issue, imo, by deletion or insertion (except at end) is we cannot even use something like memcopy because the source & target mem areas overlap (indeed). D also refuses idioms like (to delete 1 elem): a[i..$-1]=a[i+1..$]; for the same reason. Shifting elems by hand from insertion/deletion point is indeed not cheap, but avoids copying *all* (remaining) elements as is done by concat. I think there should be one builtin array-elem-shift functions that does that (also because it's easy to have wrong, since one must proceed backwards on insertion). The obvious process of the function (indicated by its name), and the fact that it is not called insert/delete, would clearly tell I guess that this is not cheap; while still providing the functionality. What do you all think? So, well, I'll just concatenate in the meantime. Denis -- _ vita es estrany spir.wikidot.com
Re: array idioms
On 02/25/2011 11:31 PM, Andrej Mitrovic wrote: On 2/25/11, spir wrote: But where is this func implemented? DMD\dmd2\src\druntime\src\rt\aaA.d _aaDel&& _aaDelX And then in object.d: extern (C) { // from druntime/src/compiler/dmd/aaA.d ... void _aaDel(void* p, TypeInfo keyti, ...); ... } I don't really know how it gets called since I don't see any explicit calls to this function. This probably requires more insight into how druntime and dmd work together. Thanks, Andrej. Denis -- _ vita es estrany spir.wikidot.com
Re: std.xml empty element
On 2011-02-25 21:11, Tom wrote: El 24/02/2011 19:40, Tom escribió: El 24/02/2011 09:51, Jacob Carlborg escribió: On 2011-02-24 06:48, Tom wrote: Hi, how can I create an empty element with current D2 std.xml Element implementation? stdout.writeln(new Element("foo")); // Shields instead of Thanks in advance, Tom; http://d.puremagic.com/issues/show_bug.cgi?id=4394 I see :( Thanks... Lucky me, 2.052 solves this bug and doesn't break anything. Tom; Really? Which changeset? -- /Jacob Carlborg
Re: How do you test pre-/post-conditions and invariants?
On 02/25/2011 11:20 PM, Magnus Lie Hetland wrote: On 2011-02-25 17:48:54 +0100, spir said: On 02/25/2011 04:30 PM, Magnus Lie Hetland wrote: Or, more generally, how do you test asserts (which is what I'm using in my preconditions etc.)? As far as I can see, collectException() won't collect errors, which is what assert() throws -- so what's the standard way of writing unit tests for preconditions that use assert? (I.e., test that they will, in fact, throw when you break them.) See the page on DbC: http://www.digitalmars.com/d/2.0/dbc.html. Denis Hm. I'm not sure how this answers my question. I know how pre/postconditions etc. work -- I was asking for how to test them in a unit test (i.e., ensure that they'll kick in if you provide faulty intput, for example). Maybe I'm missing something in the doc you referred me to? No, sorry, /I/ read your post too superficially: Hadn't caught you wanted to "meta-check" the checks. Denis -- _ vita es estrany spir.wikidot.com
Re: How do you test pre-/post-conditions and invariants?
On 02/25/2011 11:33 PM, Magnus Lie Hetland wrote: On 2011-02-25 20:04:10 +0100, Jonathan M Davis said: On Friday, February 25, 2011 07:30:50 Magnus Lie Hetland wrote: Or, more generally, how do you test asserts (which is what I'm using in my preconditions etc.)? As far as I can see, collectException() won't collect errors, which is what assert() throws -- so what's the standard way of writing unit tests for preconditions that use assert? (I.e., test that they will, in fact, throw when you break them.) I think that the reality of the matter is the most of the time people _don't_ check them. And on some level, it doesn't make sense to. It's kind of like asking how people test their unit tests. Unit tests are already testing code. Do you want to be testing them on top of that? And if you do, do you test _that_ code? Where do you stop? I guess so. But you could say the same thing about other cases where you throw an exception when you detect that something is wrong -- but those are normally tested, right? Also, the difference here is that the precondition is written as a general "test", whereas my actual test would have specific cases. For example, I have a test that checks that I don't add the same object twice to some structure, and the check involves some traversal -- code that could potentially be wrong. I wanted to make sure that it wasn't by explicitly adding the same object twice -- code (i.e., my unit test) that most likely could not be wrong. But I do see your point. Now that you speak of it, I do agree with you. Just like for code paths or specific inputs that should throw an exception. I systematically check these bits in unittests. It's very easy to have them right, if only by distraction because they are not the points on which with we put most attention, and there often is a test invertion somewhere (and we don't watch them run). And actually, I often find an error somewhere in there. What I do is trigger them in unitests, check all works as expected (ie an error is raised, and the message is sensible), then comment out but /keep/ the testing code. Dunno if this makes sense for DbC checkings. Denis -- _ vita es estrany spir.wikidot.com
Re: How do you test pre-/post-conditions and invariants?
On Friday, February 25, 2011 14:33:20 Magnus Lie Hetland wrote: > On 2011-02-25 20:04:10 +0100, Jonathan M Davis said: > > On Friday, February 25, 2011 07:30:50 Magnus Lie Hetland wrote: > >> Or, more generally, how do you test asserts (which is what I'm using in > >> my preconditions etc.)? > >> > >> As far as I can see, collectException() won't collect errors, which is > >> what assert() throws -- so what's the standard way of writing unit > >> tests for preconditions that use assert? (I.e., test that they will, in > >> fact, throw when you break them.) > > > > I think that the reality of the matter is the most of the time people > > _don't_ check them. And on some level, it doesn't make sense to. It's > > kind of like asking how people test their unit tests. Unit tests are > > already testing code. Do > > you want to be testing them on top of that? And if you do, do you test > > _that_ code? Where do you stop? > > I guess so. But you could say the same thing about other cases where > you throw an exception when you detect that something is wrong -- but > those are normally tested, right? Also, the difference here is that the > precondition is written as a general "test", whereas my actual test > would have specific cases. > > For example, I have a test that checks that I don't add the same object > twice to some structure, and the check involves some traversal -- code > that could potentially be wrong. I wanted to make sure that it wasn't > by explicitly adding the same object twice -- code (i.e., my unit test) > that most likely could not be wrong. > > But I do see your point. > > [snip] > > > And testing post-conditions and invariants in the manner that you're > > trying to do borders on impossible. What are you going to do, repeat the > > post-condition or > > invariant test on the result of the function or on the state of the > > object that the function was called on after the function was called? > > That's just doing the test twice. > > Right. > > > You might as well just re-read the post-conditions and invariants to > > make sure that you wrote them correctly. > > > > I do see value in testing pre-conditions if you're using exceptions > > rather than assertions (which means that you're not use in blocks). In > > that case, you're testing the API to make sure that it does what it's > > supposed to do. But if you're dealing with assertions, then it's really > > test code as opposed to API code, and I don't see the same value in > > testing that. You'd just be testing test > > code. > > OK. For the practical reason, I refer you to my explanation above. But > I guess it's a style issue -- and I'm fine with not testing these > things, by all means. When using assertions, you're checking the logic of your program and they should _always_ be true. When using exceptions, it's something that can conceivably fail at runtime. And if you view your function or class/struct as being part of an API, then you don't know who or what code will be using it, so it generally makes sense to use exceptions. If you use a pre-condition and assert that input is valid, then you're really testing the code that's calling your function, not the function itself. So, using such assertions makes good sense when you control both the caller and the callee and it's something that should never happen. However, if you don't necessarily control the caller or if it's something that _could_ happen at runtime (even if it shouldn't), then an exception makes a lot more sense. I tend to view exceptions as part of the API and think that they should be tested. Assertions, on the other hand, aren't really part of the API, since they go away in release mode, and I therefore view them as test code. They're verifying that your logic is correct. So, on some level, it is indeed a stylistic thing, but where you choose to use exceptions and where you choose to use assertions can have a big effect on code that uses your code. > [snip] > > > Those changes _do_ make it so that you can use collectException to > > collect an Error (though it defaults to catching Exceptions only), but > > they also > > include assertThrown and assertNotThrown which effectively assert that > > the Exception or Error that you expected to be thrown (or not) from a > > particular expression or function call was indeed thrown (or not). > > So, you _can_ use that with AssertError to verify your pre-conditions. > > OK, thanks. > > > However, I would point out that catching Errors is generally a _bad_ > > idea. > > [snip lots of useful stuff] > > Thanks for educating me :D > > I guess the conclusion will be that I'll focus on keeping my > preconditions really simple. (And any utility functions I use in them > can then get unit tests of their own instead ;) That's probably a good way to handle it. I find that I often tend to have helper functions like that simply because I end up testing the same thing in a variety of places, and I don't
Interfacing with c and platform dependent sizes
C is not my strong side, so I'm having some problems wrapping some code. I found a couple of sources on this: 1) http://www.digitalmars.com/d/2.0/htomodule.html 2) http://www.digitalmars.com/d/2.0/interfaceToC.html 1) C's long is the same as D's int. long long is long 2) C 32bit's long long is D's long, C 64 bits long is D's long. So.. A long in C is the same as the platform size? And long long doesn't exist in 64 bit?
Multiple assignment
Is this program showing a bug in multiple assignments (DMD 2.052)? void main() { int i; int[2] x; i, x[i] = 1; assert(x == [1, 0]); // OK int j; int[2] y; y[j], j = 1; assert(y == [0, 0]); // Not OK } At the end of the program I expect y to be [1,0] instead of [0,0]. Yet this C program with GCC: #include "stdio.h" int main() { int i = 0; int x[2] = {0, 0}; i, x[i] = 1; printf("%d %d\n", x[0], x[1]); int j = 0; int y[2] = {0, 0}; y[j], j = 1; printf("%d %d\n", y[0], y[1]); return 0; } has the same output as DMD: 1 0 0 0 Bye, bearophile
Re: Multiple assignment
On 26.02.2011 01:56, bearophile wrote: Is this program showing a bug in multiple assignments (DMD 2.052)? void main() { int i; int[2] x; i, x[i] = 1; assert(x == [1, 0]); // OK int j; int[2] y; y[j], j = 1; assert(y == [0, 0]); // Not OK } At the end of the program I expect y to be [1,0] instead of [0,0]. Yet this C program with GCC: #include "stdio.h" int main() { int i = 0; int x[2] = {0, 0}; i, x[i] = 1; printf("%d %d\n", x[0], x[1]); int j = 0; int y[2] = {0, 0}; y[j], j = 1; printf("%d %d\n", y[0], y[1]); return 0; } has the same output as DMD: 1 0 0 0 Bye, bearophile I couldn't find any info on the comma expression in the language reference, but this was my first google hit: """ A comma expression contains two operands of any type separated by a comma and has *left-to-right* associativity. The left operand is fully evaluated, possibly producing side effects, and its value, if there is one, is *discarded*. The right operand is then evaluated. The type and value of the result of a comma expression are those of its right operand, after the usual unary conversions """
Re: Interfacing with c and platform dependent sizes
simendsjo: > So.. A long in C is the same as the platform size? And long long doesn't > exist in 64 bit? In D the size of int/uint is 32 bits and long/ulong is 64 bits. In C the size of int, unsigned int, long, long long int, unsigned long long int, etc are not fixed, the change according to the CPU. sizeof(int) <= sizeof(long) <= sizeof(long long). A help: http://www.digitalmars.com/d/2.0/phobos/std_stdint.html Bye, bearophile
Re: Multiple assignment
On 02/25/2011 04:56 PM, bearophile wrote: > Is this program showing a bug in multiple assignments (DMD 2.052)? > > > void main() { > int i; > int[2] x; > i, x[i] = 1; I haven't heard about multiple assignments but that's the comma operator up there, separating (and sequencing) two expressions: 1) i 2) x[i] = 1 > assert(x == [1, 0]); // OK > > int j; > int[2] y; > y[j], j = 1; Again, two expressions: 1) y[j] 2) j = 1 Only the second of both cases have an effect. Ali > assert(y == [0, 0]); // Not OK > } > > > At the end of the program I expect y to be [1,0] instead of [0,0]. > > Yet this C program with GCC: > > #include "stdio.h" > int main() { > int i = 0; > int x[2] = {0, 0}; > i, x[i] = 1; > printf("%d %d\n", x[0], x[1]); > > int j = 0; > int y[2] = {0, 0}; > y[j], j = 1; > printf("%d %d\n", y[0], y[1]); > > return 0; > } > > > has the same output as DMD: > 1 0 > 0 0 > > Bye, > bearophile
Re: Multiple assignment
simendsjo: > I couldn't find any info on the comma expression in the language > reference, but this was my first google hit: > """ > A comma expression contains two operands of any type separated by a > comma and has *left-to-right* associativity. The left operand is fully > evaluated, possibly producing side effects, and its value, if there is > one, is *discarded*. The right operand is then evaluated. The type and > value of the result of a comma expression are those of its right > operand, after the usual unary conversions > """ Right. But my code was wrong, I meant to write this: void main() { int i; int[2] x; i = x[i] = 1; assert(x == [1, 0]); // OK int j; int[2] y; y[j] = j = 1; assert(y == [0, 1]); // Not OK } And I think it is working as you expect it to. Thank you and sorry for the noise, bearophile
Re: Interfacing with c and platform dependent sizes
On 26.02.2011 02:06, bearophile wrote: simendsjo: So.. A long in C is the same as the platform size? And long long doesn't exist in 64 bit? In D the size of int/uint is 32 bits and long/ulong is 64 bits. In C the size of int, unsigned int, long, long long int, unsigned long long int, etc are not fixed, the change according to the CPU. sizeof(int)<= sizeof(long)<= sizeof(long long). A help: http://www.digitalmars.com/d/2.0/phobos/std_stdint.html Bye, bearophile Ouch.. Any tips on porting C code that would work nicely with a transition to 64 bit? Should I change all long and int to int_atleast_32_t and long long to 64?
Re: Interfacing with c and platform dependent sizes
On Friday, February 25, 2011 17:16:31 simendsjo wrote: > On 26.02.2011 02:06, bearophile wrote: > > simendsjo: > >> So.. A long in C is the same as the platform size? And long long doesn't > >> exist in 64 bit? > > > > In D the size of int/uint is 32 bits and long/ulong is 64 bits. > > > > In C the size of int, unsigned int, long, long long int, unsigned long > > long int, etc are not fixed, the change according to the CPU. > > sizeof(int)<= sizeof(long)<= sizeof(long long). > > > > A help: > > http://www.digitalmars.com/d/2.0/phobos/std_stdint.html > > > > Bye, > > bearophile > > Ouch.. Any tips on porting C code that would work nicely with a > transition to 64 bit? > Should I change all long and int to int_atleast_32_t and long long to 64? It depends entirely on what the code is doing. It could be completely safe to convert all ints, longs, and long longs to long to long. Or you may have to choose int or long depending on what system the code is supposed to be for. In many cases, using a larger type wouldn't matter, since it can hold more than the smaller type, so whether the type in C/C++ was 32 bits or 64 bits is irrelevant. In other cases, the type needs to be an exact size, because the code is doing bit shifts or whatnot (in which case they _should_ have been using int32_t and int64_t on Linux and whatever the equivalent is on Windows, but unfortunately, many programmers don't). And if you're dealing with a struct, it's possible that that struct has to be an exact size (e.g. for some binary format), and using the wrong type in converting could make it the wrong size. If you want to know what the appropriate D type is for the C/C++ code, you _need_ to know what it does. Now, IIRC, int is almost guaranteed to be 32 bits at this point, and long long is essentially guaranteed to be 64 bits, but long varies from system to system - both in terms of OS and architecture. IIRC, long is 32 bits on Solaris and Windows - both on x86 and x86_64 - but it's 32 bits in x86 Linux and 64 bits in x86_64 Linux. So, if all the code uses is int and long long, then it's probably reasonably safe to use int for int and long for long long, but it's ultimately system dependent. Personally, I would argue that C/C++ code should use int when you don't care about the size of an integral type and use the intX_t types (where X is 8, 16, 32, or 64) when you _do_ care about the size, but there's no guarantee that programmers are going to be that disciplined about it. In any case, if you really don't know the code and don't want to take the time to understand it, I'd use int for int, long for long long, and then if they have long, I'd do the research to figure out which OS and architecture the code is supposed to be for and use int if long long is 32 bits and long if it's 64 bits. If you don't know what system it was built for, then I'd probably just use long and hoped that they weren't doing anything that made using an integral type which was too large a problem. - Jonathan M Davis
Re: Multiple assignment
On 02/25/2011 05:09 PM, bearophile wrote: > int j; > int[2] y; > y[j] = j = 1; I think that's undefined behavior in C and C++. It is not defined whether j's previous or past value is used in y[j]. I would expect the situation be the same in D. Ali
Re: Multiple assignment
On Friday, February 25, 2011 17:31:36 Ali Çehreli wrote: > On 02/25/2011 05:09 PM, bearophile wrote: > > int j; > > int[2] y; > > y[j] = j = 1; > > I think that's undefined behavior in C and C++. It is not defined > whether j's previous or past value is used in y[j]. > > I would expect the situation be the same in D. No, that should be perfectly defined. What's undefined is when you do something like func(j, y[j]). The evaluation order of the function arguments is undefined. However, the evaluation order when dealing with an assignment should be defined. I _could_ be wrong about that, but there's no question that the assignments themselves are guaranteed to be done in right-to-left order. - Jonathan M Davis
Re: implicite deref on array element access? (indexing)
On Friday, February 25, 2011 07:15:52 spir wrote: > Hello, > > I thought it worked, just like implicite deref on (struct, class) member > access. But I cannot have it work: > > auto a = [1,2,3]; > auto pa = &a; > writeln((*pa)[2]); // ok > writeln(pa[2]); // segfault > > Denis The _only_ time that dereferencing is done automatically in D is with the dot operator. - Jonathan M Davis
Re: Interfacing with c and platform dependent sizes
On Fri, 25 Feb 2011 20:06:04 -0500, bearophile wrote: simendsjo: So.. A long in C is the same as the platform size? And long long doesn't exist in 64 bit? In D the size of int/uint is 32 bits and long/ulong is 64 bits. In C the size of int, unsigned int, long, long long int, unsigned long long int, etc are not fixed, the change according to the CPU. sizeof(int) <= sizeof(long) <= sizeof(long long). It's *recommended* that ints be the size of a standard register. So, those sizes do not have to follow the CPU architecture, and compilers could potentially use different sizes even on the same platform. D (and most languages that came after C) did a much better job on this. BTW, I think long long is a gnu extension, it's not standard C (I don't think long long exists in Visual C for instance). -Steve
Re: Multiple assignment
On Fri, 25 Feb 2011 21:10:59 -0500, Jonathan M Davis wrote: On Friday, February 25, 2011 17:31:36 Ali Çehreli wrote: On 02/25/2011 05:09 PM, bearophile wrote: > int j; > int[2] y; > y[j] = j = 1; I think that's undefined behavior in C and C++. It is not defined whether j's previous or past value is used in y[j]. I would expect the situation be the same in D. No, that should be perfectly defined. What's undefined is when you do something like func(j, y[j]). The evaluation order of the function arguments is undefined. However, the evaluation order when dealing with an assignment should be defined. I _could_ be wrong about that, but there's no question that the assignments themselves are guaranteed to be done in right-to-left order. Let me fix that for you: func(j++, y[j]) -Steve
Re: Multiple assignment
On Friday, February 25, 2011 19:26:14 Steven Schveighoffer wrote: > On Fri, 25 Feb 2011 21:10:59 -0500, Jonathan M Davis > > wrote: > > On Friday, February 25, 2011 17:31:36 Ali Çehreli wrote: > >> On 02/25/2011 05:09 PM, bearophile wrote: > >> > int j; > >> > int[2] y; > >> > y[j] = j = 1; > >> > >> I think that's undefined behavior in C and C++. It is not defined > >> whether j's previous or past value is used in y[j]. > >> > >> I would expect the situation be the same in D. > > > > No, that should be perfectly defined. What's undefined is when you do > > something > > like func(j, y[j]). The evaluation order of the function arguments is > > undefined. > > However, the evaluation order when dealing with an assignment should be > > defined. > > I _could_ be wrong about that, but there's no question that the > > assignments > > themselves are guaranteed to be done in right-to-left order. > > Let me fix that for you: > > func(j++, y[j]) LOL. Yes. I forgot to alter j in the expression. Good catch. - Jonathan M Davis
Re: Interfacing with c and platform dependent sizes
On Friday, February 25, 2011 17:35:02 Jonathan M Davis wrote: > On Friday, February 25, 2011 17:16:31 simendsjo wrote: > > On 26.02.2011 02:06, bearophile wrote: > > > simendsjo: > > >> So.. A long in C is the same as the platform size? And long long > > >> doesn't exist in 64 bit? > > > > > > In D the size of int/uint is 32 bits and long/ulong is 64 bits. > > > > > > In C the size of int, unsigned int, long, long long int, unsigned long > > > long int, etc are not fixed, the change according to the CPU. > > > sizeof(int)<= sizeof(long)<= sizeof(long long). > > > > > > A help: > > > http://www.digitalmars.com/d/2.0/phobos/std_stdint.html > > > > > > Bye, > > > bearophile > > > > Ouch.. Any tips on porting C code that would work nicely with a > > transition to 64 bit? > > Should I change all long and int to int_atleast_32_t and long long to 64? > > It depends entirely on what the code is doing. It could be completely safe > to convert all ints, longs, and long longs to long to long. Or you may > have to choose int or long depending on what system the code is supposed > to be for. > > In many cases, using a larger type wouldn't matter, since it can hold more > than the smaller type, so whether the type in C/C++ was 32 bits or 64 bits > is irrelevant. In other cases, the type needs to be an exact size, because > the code is doing bit shifts or whatnot (in which case they _should_ have > been using int32_t and int64_t on Linux and whatever the equivalent is on > Windows, but unfortunately, many programmers don't). And if you're dealing > with a struct, it's possible that that struct has to be an exact size > (e.g. for some binary format), and using the wrong type in converting > could make it the wrong size. > > If you want to know what the appropriate D type is for the C/C++ code, you > _need_ to know what it does. Now, IIRC, int is almost guaranteed to be 32 > bits at this point, and long long is essentially guaranteed to be 64 bits, > but long varies from system to system - both in terms of OS and > architecture. IIRC, long is 32 bits on Solaris and Windows - both on x86 > and x86_64 - but it's 32 bits in x86 Linux and 64 bits in x86_64 Linux. > So, if all the code uses is int and long long, then it's probably > reasonably safe to use int for int and long for long long, but it's > ultimately system dependent. Personally, I would argue that C/C++ code > should use int when you don't care about the size of an integral type and > use the intX_t types (where X is 8, 16, 32, or 64) when you _do_ care > about the size, but there's no guarantee that programmers are going to be > that disciplined about it. > > In any case, if you really don't know the code and don't want to take the > time to understand it, I'd use int for int, long for long long, and then > if they have long, I'd do the research to figure out which OS and > architecture the code is supposed to be for and use int if long long is 32 > bits and long if it's 64 bits. If you don't know what system it was built > for, then I'd probably just use long and hoped that they weren't doing > anything that made using an integral type which was too large a problem. Actually, I just realized that I was thinking in terms of porting C++ code to D. You're going to have to be more strict if you're just converting header files. However, what you can do is just compile something like this in C/C++ on your system: printf("int -> %d bytes", sizeof(int)); printf("long -> %d bytes", sizeof(long)); printf("long long -> %d bytes", sizeof(long long)); Then you'll know what they are on your system, and you can convert them over just fine. You just have to remember to do the same on any other system that you compile your code on. Bleh. At least D went the route of standarizing the size of its primitive types. - Jonathan M Davis
Re: std.xml empty element
El 25/02/2011 20:07, Jacob Carlborg escribió: On 2011-02-25 21:11, Tom wrote: El 24/02/2011 19:40, Tom escribió: El 24/02/2011 09:51, Jacob Carlborg escribió: On 2011-02-24 06:48, Tom wrote: Hi, how can I create an empty element with current D2 std.xml Element implementation? stdout.writeln(new Element("foo")); // Shields instead of Thanks in advance, Tom; http://d.puremagic.com/issues/show_bug.cgi?id=4394 I see :( Thanks... Lucky me, 2.052 solves this bug and doesn't break anything. Tom; Really? Which changeset? Not sure what you mean, but it seems it got fixed when 4069 was resolved... http://d.puremagic.com/issues/show_bug.cgi?id=4069 Tom;
Re: Multiple assignment
On 02/25/2011 06:10 PM, Jonathan M Davis wrote: On Friday, February 25, 2011 17:31:36 Ali Çehreli wrote: On 02/25/2011 05:09 PM, bearophile wrote: > int j; > int[2] y; > y[j] = j = 1; I think that's undefined behavior in C and C++. It is not defined whether j's previous or past value is used in y[j]. I would expect the situation be the same in D. No, that should be perfectly defined. What's undefined is when you do something like func(j, y[j]). The evaluation order of the function arguments is undefined. However, the evaluation order when dealing with an assignment should be defined. I _could_ be wrong about that, but there's no question that the assignments themselves are guaranteed to be done in right-to-left order. - Jonathan M Davis Standard texts are very difficult to read. I found a 2005 draft of the C++ standard. 5 Expressions, paragraph 4: Except where noted, the order of evaluation of operands of individual operators and subexpressions of individual expres- sions, and the order in which side effects take place, is unspecified.58) Between the previous and next sequence point a scalar object shall have its stored value modified at most once by the evaluation of an expression. Furthermore, the prior value shall be accessed only to determine the value to be stored. The requirements of this paragraph shall be met for each allowable ordering of the subexpressions of a full expression; otherwise the behavior is undefined. [ Example: i = v [ i ++]; / / the behavior is undefined i = 7 , i ++ , i ++; / / i becomes 9 i = ++ i + 1; / / the behavior is undefined i = i + 1; / / the value of i is incremented — end example ] To complete, footnote 58 is: 58) The precedence of operators is not directly specified, but it can be derived from the syntax. The section for the assignment operator does not mention anything to the contrary. According to my current understanding and my now-hazy recollections of old discussions on C++ news groups, in the following statement a() = b() = c(); the value of c() is assigned to b(), and the value of that expression is assigned to a(); but the order in which the three expressions are evaluated are unspecified. Hence, if the code behaves contrary to 5.1 above, it has undefined behavior. This was bearophile's statement: y[j] = j = 1; The assignment operators do not introduce sequence points; there are only two: before and after the whole line above. The code does not obey "the prior value shall be accessed only to determine the value to be stored". Above, the prior value is used to determine which element of y is being assigned to. Ali
Re: Multiple assignment
On Friday 25 February 2011 22:32:47 Ali Çehreli wrote: > On 02/25/2011 06:10 PM, Jonathan M Davis wrote: > > On Friday, February 25, 2011 17:31:36 Ali Çehreli wrote: > >> On 02/25/2011 05:09 PM, bearophile wrote: > >> > int j; > >> > int[2] y; > >> > y[j] = j = 1; > >> > >> I think that's undefined behavior in C and C++. It is not defined > >> whether j's previous or past value is used in y[j]. > >> > >> I would expect the situation be the same in D. > > > > No, that should be perfectly defined. What's undefined is when you do > > something like func(j, y[j]). The evaluation order of the function > > arguments is undefined. However, the evaluation order when dealing with > > an assignment should be defined. I _could_ be wrong about that, but > > there's no question that the assignments themselves are guaranteed to be > > done in right-to-left order. > > > > - Jonathan M Davis > > Standard texts are very difficult to read. I found a 2005 draft of the > C++ standard. 5 Expressions, paragraph 4: > > > Except where noted, the order of evaluation of operands of individual > operators and subexpressions of individual expres- > sions, and the order in which side effects take place, is > unspecified.58) Between the previous and next sequence point a > scalar object shall have its stored value modified at most once by the > evaluation of an expression. Furthermore, the prior >value shall be accessed only to determine the value to be stored. The > requirements of this paragraph shall be met for > each allowable ordering of the subexpressions of a full expression; > otherwise the behavior is undefined. [ Example: > i = v [ i ++]; / / the behavior is undefined > i = 7 , i ++ , i ++; / / i becomes 9 > i = ++ i + 1; / / the behavior is undefined > i = i + 1; / / the value of i is incremented > — end example ] > > > To complete, footnote 58 is: > > > 58) > The precedence of operators is not directly specified, but it can be > derived from the syntax. > > > The section for the assignment operator does not mention anything to the > contrary. According to my current understanding and my now-hazy > recollections of old discussions on C++ news groups, in the following > statement > >a() = b() = c(); > > the value of c() is assigned to b(), and the value of that expression is > assigned to a(); but the order in which the three expressions are > evaluated are unspecified. > > Hence, if the code behaves contrary to 5.1 above, it has undefined > behavior. > > This was bearophile's statement: > >y[j] = j = 1; > > The assignment operators do not introduce sequence points; there are > only two: before and after the whole line above. The code does not obey > "the prior value shall be accessed only to determine the value to be > stored". Above, the prior value is used to determine which element of y > is being assigned to. Bleh. Well, good to know. Walter wants to make the order such evaluations ordered in D at some point though, so eventually it won't be a problem in D - though it'll obviously still be a problem in C++. Regardless, avoiding to alter a variable and use it multiple times within the same statement or expression is a good idea. - Jonathan M davis