Re: ddoc file on command line
I forgot to mention that I'm using the latest (beta) version of DMD 2 on Windows XP. On Tue, 10 Aug 2010 20:52:18 -0500, Yao G. wrote: According to the DDOC spec (http://digitalmars.com/d/2.0/ddoc.html) if you want to redefine some macros, one way is to pass one file with the .ddoc extension to the command line, but it doesn't work in my setup. For example, suppose I have the file yao.date.calendar, and I want to generate the documentation, so I compile with: % dmd.exe calendar.d docbook.ddoc -Dfcalendar.xml And it doesn't work. Am I doing something wrong? Note that the file is generated correctly but the few macros that I redefine (DDOC, DDOC_SUMMARY, etc.) don't get replaced with the new ones. The docbook.ddoc is on the same directory where I have the *.d files (code). Thanks in advance. -- Yao G.
ddoc file on command line
According to the DDOC spec (http://digitalmars.com/d/2.0/ddoc.html) if you want to redefine some macros, one way is to pass one file with the .ddoc extension to the command line, but it doesn't work in my setup. For example, suppose I have the file yao.date.calendar, and I want to generate the documentation, so I compile with: % dmd.exe calendar.d docbook.ddoc -Dfcalendar.xml And it doesn't work. Am I doing something wrong? Note that the file is generated correctly but the few macros that I redefine (DDOC, DDOC_SUMMARY, etc.) don't get replaced with the new ones. The docbook.ddoc is on the same directory where I have the *.d files (code). Thanks in advance. -- Yao G.
Re: Is there a queue class in phobos?
Wouldn't a regular array with a couple of free functions work? You will get a lot of reallocations. For non-trivial applications you need some more sophisticated approach to alter the size of the array and maybe also deterministic memory management. A queue is a commonly used technique so so it's justified to have it in the standard library, just like lists, heaps etc.
Re: Sharing unlocked, unchanging data between threads?
On Tuesday, August 10, 2010 11:54:06 Jacob Carlborg wrote: > I though immutable was supposed to be implicitly shared with no need for > locks or read-write barriers (or what they're called). Ah. I have no clue that D1 does. I only use D2. There's obviously nothing wrong with posting D1 questions here, but most of the discussion and questions around here are for D2, so it's probably a good idea to indicate that you're using D1 when asking a D1-related question. - Jonathan M Davis
Re: Is there a queue class in phobos?
On Tuesday, August 10, 2010 12:06:55 Mafi wrote: > Am 10.08.2010 18:22, schrieb Trass3r: > > Container has List, BinaryHeap etc. but no Queue. Is there anything like > > that in Phobos? > > Hi, > I don't know if ther is one but I think D's arrays are powerful enough > unless you avoid the GC. > > 1. a.front() => a[0] > 2. a.popFront() => a = a[1..$] > 3. a.pushBack(x) => a ~= x > > I think in phobos there must be front and popFront for arrays to make > them ranges but I don't know where. If you want to treat an array like a range, use the functions in std.array. That's not a terribly cheap way to do things though since you keep resizing the array and will likely get a lot of reallocations. If efficiency isn't an issue, then it could be a nice, clean solution, but if efficiency is a priority, then that's probably not a good way to go. - Jonathan M Davis
Re: dsss build, tango, GC ?
Still having that apparent GC problem (with Tango on my machine), does anyone have (some GC test code) that they can recommend that I run so that I can confirm that my GC is / is not working?
Re: Is there a queue class in phobos?
Am 10.08.2010 18:22, schrieb Trass3r: Container has List, BinaryHeap etc. but no Queue. Is there anything like that in Phobos? Hi, I don't know if ther is one but I think D's arrays are powerful enough unless you avoid the GC. 1. a.front() => a[0] 2. a.popFront() => a = a[1..$] 3. a.pushBack(x) => a ~= x I think in phobos there must be front and popFront for arrays to make them ranges but I don't know where.
Re: Sharing unlocked, unchanging data between threads?
On 2010-08-10 20:40, Jonathan M Davis wrote: On Tuesday, August 10, 2010 10:45:03 Chris Williams wrote: I'm writing a fairly large, multithreaded application and some part of it is causing periodic access errors. Say that I have an associative array like: uint[ char[] ] nameToId; If I set all values before I start my threads going and never change anything after that point -- all access is read only -- is there any way that having multiple threads access it at the same time would mess anything up? I'm doing this in several places as locking a read-only data structure doesn't strike me as something which should be necessary. I don't know what D's associative arrays look like internally though, so perhaps it is dangerous to do. It would be a major hassle to port it all over to locking everything, to test if it fixes the problem. So, hopefully someone can say whether this is worth checking. Well, unless it's declared shared, it's going to be thread-local, and then each thread is going to have their own copy. Now, if it were declared shared and you never changed it after initially setting all of its values, then you shouldn't have any problems as far as I'm aware. Just accessing an associative array shouldn't change it. - Jonathan M Davis I though immutable was supposed to be implicitly shared with no need for locks or read-write barriers (or what they're called). -- /Jacob Carlborg
Re: Sharing unlocked, unchanging data between threads?
== Quote from Jonathan M Davis (jmdavisp...@gmail.com)'s article > Well, unless it's declared shared, it's going to be thread-local, and then each > thread is going to have their own copy. Now, if it were declared shared and you > never changed it after initially setting all of its values, then you shouldn't > have any problems as far as I'm aware. Just accessing an associative array > shouldn't change it. > - Jonathan M Davis I'm using D 1.0. I don't believe it has a "shared" keyword. But, globals are shared as well, I presume.
Re: Is there a queue class in phobos?
On 2010-08-10 18:22, Trass3r wrote: Container has List, BinaryHeap etc. but no Queue. Is there anything like that in Phobos? Wouldn't a regular array with a couple of free functions work? -- /Jacob Carlborg
Re: Sharing unlocked, unchanging data between threads?
On 10/08/2010 20:01, Steven Schveighoffer wrote: On Tue, 10 Aug 2010 13:45:03 -0400, Chris Williams wrote: I'm writing a fairly large, multithreaded application and some part of it is causing periodic access errors. Say that I have an associative array like: uint[ char[] ] nameToId; If I set all values before I start my threads going and never change anything after that point -- all access is read only -- is there any way that having multiple threads access it at the same time would mess anything up? I'm doing this in several places as locking a read-only data structure doesn't strike me as something which should be necessary. I don't know what D's associative arrays look like internally though, so perhaps it is dangerous to do. It would be a major hassle to port it all over to locking everything, to test if it fixes the problem. So, hopefully someone can say whether this is worth checking. I don't see any reason why you'd need to lock it. It should not be modified unless you change/insert a value or remove one. It's likely something else causing the issue. -Steve That and: you should probably declare it as immutable. /Max
Re: Sharing unlocked, unchanging data between threads?
On Tuesday, August 10, 2010 10:45:03 Chris Williams wrote: > I'm writing a fairly large, multithreaded application and some part > of it is causing periodic access errors. > > Say that I have an associative array like: > > uint[ char[] ] nameToId; > > If I set all values before I start my threads going and never change > anything after that point -- all access is read only -- is there any > way that having multiple threads access it at the same time would > mess anything up? I'm doing this in several places as locking a > read-only data structure doesn't strike me as something which should > be necessary. I don't know what D's associative arrays look like > internally though, so perhaps it is dangerous to do. It would be a > major hassle to port it all over to locking everything, to test if > it fixes the problem. So, hopefully someone can say whether this is > worth checking. Well, unless it's declared shared, it's going to be thread-local, and then each thread is going to have their own copy. Now, if it were declared shared and you never changed it after initially setting all of its values, then you shouldn't have any problems as far as I'm aware. Just accessing an associative array shouldn't change it. - Jonathan M Davis
Re: [OT] Is this more readable, or just way too verbose?
simendsjo wrote: > Lutger wrote: ... > I didn't increase the if nesting though. I count 2 nested if-statements inside of the foreach loop in the original, you have 3 nested if-statements. > Something like this then? Looks good to me, yes.
Re: Sharing unlocked, unchanging data between threads?
On Tue, 10 Aug 2010 13:45:03 -0400, Chris Williams wrote: I'm writing a fairly large, multithreaded application and some part of it is causing periodic access errors. Say that I have an associative array like: uint[ char[] ] nameToId; If I set all values before I start my threads going and never change anything after that point -- all access is read only -- is there any way that having multiple threads access it at the same time would mess anything up? I'm doing this in several places as locking a read-only data structure doesn't strike me as something which should be necessary. I don't know what D's associative arrays look like internally though, so perhaps it is dangerous to do. It would be a major hassle to port it all over to locking everything, to test if it fixes the problem. So, hopefully someone can say whether this is worth checking. I don't see any reason why you'd need to lock it. It should not be modified unless you change/insert a value or remove one. It's likely something else causing the issue. -Steve
Sharing unlocked, unchanging data between threads?
I'm writing a fairly large, multithreaded application and some part of it is causing periodic access errors. Say that I have an associative array like: uint[ char[] ] nameToId; If I set all values before I start my threads going and never change anything after that point -- all access is read only -- is there any way that having multiple threads access it at the same time would mess anything up? I'm doing this in several places as locking a read-only data structure doesn't strike me as something which should be necessary. I don't know what D's associative arrays look like internally though, so perhaps it is dangerous to do. It would be a major hassle to port it all over to locking everything, to test if it fixes the problem. So, hopefully someone can say whether this is worth checking.
Re: DirectX 11 bindings?
On 09/08/2010 23:12, Trass3r wrote: No one? Eugh. Nope got OpenGL 3 bindings though. -- My enormous talent is exceeded only by my outrageous laziness. http://www.ssTk.co.uk
Re: What is the term for a function that can be CTFEed?
On 10/08/2010 13:59, BCS wrote: Hello Jonathan, On Monday 09 August 2010 21:18:42 BCS wrote: We have pure functions, member functions, static functions and global functions; but what kind of function can always be used with CTFE? Haven't we typical called them CTFE or CTFEable functions? I've seen the first used, even used it my self (but it isn't even the correct part of speech) and the second is kind of hard to say. I call them F-able functions. Where F stands for Fantasic or F*ck depending on how complicated they are. -- My enormous talent is exceeded only by my outrageous laziness. http://www.ssTk.co.uk
Re: Is there a queue class in phobos?
On Tuesday, August 10, 2010 09:22:16 Trass3r wrote: > Container has List, BinaryHeap etc. but no Queue. Is there anything like > that in Phobos? At the moment, I believe that what you see is what you get. std.container is quite young, and there are definitely going to be more containers in it, but for the moment, it's a bit sparse. It's a definite improvement over no containers, but it's new enough that it's still lacking in the number of containers that it has. - Jonathan M Davis
std.getopt in 2.047
Hello, I've noticed that documentation does not reflect what std.getopt does concerning endOfOptions ("--"). Documentation: Options Terminator A lonesome double-dash terminates getopt gathering. It is used to separate program options from other parameters (e.g. options to be passed to another program). Invoking the example above with "--foo -- --bar" parses foo but leaves "--bar" in args. The double-dash itself is removed from the argument array. --- But the double-dash is not removed. I've encountered this while testing a small program, but then looked at std.getopt.d, and indeed handleOption just breaks on endOfOptions without removing it. Is this a documentation error or Phobos bug? -- **
Is there a queue class in phobos?
Container has List, BinaryHeap etc. but no Queue. Is there anything like that in Phobos?
Re: std.string.chomp error
On Tuesday 10 August 2010 02:34:33 Lars T. Kyllingstad wrote: > I guess it depends on what behaviour you're after. In the present case, > if you want chomp(a, null) and chomp(a, "") to do the same thing, then > you should use '=='. If you want chomp(a, "") to simply do nothing, use > 'is'. I just figured that the former was the desired behaviour here. If > it isn't, I agree with you. :) I was really talking about the general case rather than chomp() in specific, but's fine with me if "" and null are treated the same here, I suppose. Still, I really don't like it when null and empty is treated the same way (in D or anything else). There's a difference between something not existing and it existing but not having anything in it. But, as I said, we're stuck with the way it is in D. - Jonathan M Davis
Re: Casting away const
On Mon, 09 Aug 2010 19:35:38 -0400, Jonathan M Davis wrote: On Monday, August 09, 2010 15:01:28 Steven Schveighoffer wrote: Then the author failed to make it const, and it's a bug in the function definition. "Casting away const if you don't write" is crap, and should be treated as suspiciously as code that writes to const data. I totally agree that the author of the code screwed up. However, sometimes you have to deal with other people's screw ups. And unfortunately, in my experience, a _lot_ of programmers don't bother to write const-correct code, and it causes huge problems for those of us who do. Yes, but by using such code and casting away const you are: 1) opening up your application to potential undefined behavior if the code you are using changes in a way that actually *does* write to the object 2) opening up your *own* code to potential undefined behavior in case you accidentally forget that you casted away const. Casting away const is bad unless you control all the elements involved, and I think you need to limit it to small pieces of code where you scrutinize every aspect of it. I think creating a Mutable wrapper for a type can potentially be an asset if it's done correctly. What if calculating the hash is expensive, and you know you don't have to recalculate it, you might cache it as a member of the class. Believe me, if a programmer can do it, he will. Documentation saying "don't do this!" isn't enough. That's why mutable would be highly desirable, but we don't have it so tough luck for us on that count, I suppose. As for documentation, if the function is const, then no documentation is necessary. They just can't do it (not without casting away constness and going into undefined territory anyway). As long as its encapsulated, I think we are ok. Note that there are other parts of the instance that are always mutable, such as the monitor object. Personally, I'd say tough luck to the guy who wants to cache the hash by calculating it in toHash(). He can call some other function to cache it, or he could have a non-const version which caches it for cases where the object isn't const, or he could calculate it when something in the class changes (which naturally comes with its own set of pros and cons). From the perspective of logical constness, there is no reason why toHash() can't be const. I've proven that logical const is doable without breaking const in a post a couple years ago. It's just lacking the language support. I also made an extremely complex proposal to allow specification of various levels of const but that was rejected on account of being too complex :) But looking at things like Rebindable, I think we should be able to make a logical const type that allows what we need in a controlled manner. The one thing that stumps me is why associative arrays allow for const keys with toHash() not being const. If I were to try and write a hashtable implementation myself, I'd have to cast away the constness of the keys to be able to call toHash() on them, which would be _really_ annoying. Maybe that's what associative arrays are doing internally. hehe, AA's are part of the runtime, so they manually must obey const rules. Basically, they get a TypeInfo and a void * (which the compiler strips of any const or type) and have to do the right thing. The TypeInfo's getHash() function takes a void *, so no const is obeyed, that's why it works. Personally, I tend to be of the opinion that if a function can be const, it should be const. There are always exceptions of course, but generally I think that functions should be const when possible. It allows for writing const- correct code much more easily (if not just outright makes it possible), and that can reduce the number of mutation bugs that programmers have to deal with. I agree. -Steve
Re: Shifting values within an array
On Tue, 10 Aug 2010 09:01:28 -0400, Chris Williams wrote: I would like to be able to do something like this: class A { int i; } int main() { A[] list; for (uint L = 0; L < 3; L++) { for (uint L2 = 0; L2 < 3; L2++) { uint index = L + L2; uint copyAmount = list.length - index; list.length = list.length + 1; if (copyAmount > 0) { // Move data after index one slot later to make room A[] sliceFrom = list[index .. (index + copyAmount)]; A[] sliceTo = list[(index + 1) .. (index + 1 + copyAmount)]; sliceTo[] = sliceFrom[]; } list[index] = new A(); list[index].i = index; } } return 0; } I have a running implementation which uses C's memmove(), but I gather that this isn't a safe means to do it as the garbage collector might run while the references to the object are being manipulated. Is there a way to do this outside of a loop? I think memmove should be fine. All thread stacks are scanned during GC cycles, so there is no danger of having one element get collected. I think memmove will not copy half a reference anyways. -Steve
Shifting values within an array
I would like to be able to do something like this: class A { int i; } int main() { A[] list; for (uint L = 0; L < 3; L++) { for (uint L2 = 0; L2 < 3; L2++) { uint index = L + L2; uint copyAmount = list.length - index; list.length = list.length + 1; if (copyAmount > 0) { // Move data after index one slot later to make room A[] sliceFrom = list[index .. (index + copyAmount)]; A[] sliceTo = list[(index + 1) .. (index + 1 + copyAmount)]; sliceTo[] = sliceFrom[]; } list[index] = new A(); list[index].i = index; } } return 0; } I have a running implementation which uses C's memmove(), but I gather that this isn't a safe means to do it as the garbage collector might run while the references to the object are being manipulated. Is there a way to do this outside of a loop?
Re: What is the term for a function that can be CTFEed?
Hello Jonathan, On Monday 09 August 2010 21:18:42 BCS wrote: We have pure functions, member functions, static functions and global functions; but what kind of function can always be used with CTFE? Haven't we typical called them CTFE or CTFEable functions? I've seen the first used, even used it my self (but it isn't even the correct part of speech) and the second is kind of hard to say. -- ... <
Re: std.string.chomp error
Lars T. Kyllingstad: > I like how it is designed now, that was my point. Sorry, I misread you.
Re: std.string.chomp error
On Tue, 10 Aug 2010 07:50:34 -0400, bearophile wrote: > Lars T. Kyllingstad: >> There, I don't agree with you. Arrays are a sort of pseudo-reference >> type, so I don't mind 'null' being a sort of pseudo-null in that >> context. Actually, I find it to be quite elegant. It's a matter of >> taste, I guess. > > I suggest you to write down the things you don't like and the design you > desire here. ?? I like how it is designed now, that was my point. -Lars
Re: std.string.chomp error
Lars T. Kyllingstad: > There, I don't agree with you. Arrays are a sort of pseudo-reference > type, so I don't mind 'null' being a sort of pseudo-null in that > context. Actually, I find it to be quite elegant. It's a matter of > taste, I guess. I suggest you to write down the things you don't like and the design you desire here. Bye, bearophile
Re: [OT] Is this more readable, or just way too verbose?
Lutger wrote: simendsjo wrote: (...) The CR and LF constants are a bit too much, probably because they don't really abstract over the literals which I can actually parse faster. The isCR and isLF are nice however. Taking it a step further: bool canSplit = inPattern(c,"\r\n"); if (canSplit) { ... You have increased the nesting of ifs to 3 inside a for-loop.Personally I don't read deep nesting very well. To go for readability I would use a small function for the entire expression: if( s[i..$].startsWithCRLF() ) // same as startsWithCRLF(s[i..$]) { i++; istart++; } or use std.algorithm: if ( s[i..$].startsWith("\r\n") ) (...) Nice. I didn't increase the if nesting though. Something like this then? S[] mysplitlines(S)(S s) { size_t istart; auto result = Appender!(S[])(); foreach (i; 0 .. s.length) { immutable c = s[i]; immutable isEOL = inPattern(c, "\r\n"); if (isEOL) { auto beforeEOL = s[istart .. i]; result.put(beforeEOL); auto rest = s[i .. $]; immutable isCRLF = rest.startsWith("\r\n"); istart = i + 1; // consume first EOL character if (isCRLF) // skip \n too { i++; istart++; } } } // The last line might not end with EOL immutable lineNotEmpty = (istart != s.length); if (lineNotEmpty) { auto lastLine = s[istart .. $]; result.put(lastLine); } return result.data; }
Re: [OT] What is more readable?
simendsjo: > And on the other hand; I doubt anything of what I write will ever get > into phobos! If you exercise writing D code for few months you will be able contribute to Phobos2. Bye, bearophile
Re: More constants in std.string?
simendsjo: > Why a runtime error when you can have a compile time error? Because using the static type system has various kinds of costs that some people in some situations are not willing to pay. Bye, bearophile
Re: std.string.chomp error
On Tue, 10 Aug 2010 01:48:17 -0700, Jonathan M Davis wrote: > On Tuesday 10 August 2010 00:30:37 Lars T. Kyllingstad wrote: >> No, using 'is' won't work. Check this out: >> >> int[] a; >> assert (a == null); >> assert (a is null); >> >> a = new int[10]; >> a.length = 0; >> assert (a == null); >> assert (a !is null); >> >> The thing is, '==' tests whether two arrays are equal, that is, that >> they are equally long and that their elements are equal. Any empty >> array is equal to null -- in fact, in this context 'null' is just a way >> of denoting an empty array that doesn't point to any particular memory >> block (i.e. hasn't been initialised yet). >> >> // This is what '==' does >> bool mimicEquals(int[] a, int[] b) >> { >> if (a.length != b.length) return false; foreach (i; 0 .. >> a.length) if (a[i] != b[i]) return false; return true; >> } >> >> 'is', on the other hand, tests whether two arrays are identical, i.e. >> that they have the same length and *refer to the same piece of memory*. >> >> // This is (sort of) what 'is' does >> bool mimicIs(int[] a, int[] b) >> { >> return (a.ptr == b.ptr && a.length == b.length); >> } >> >> -Lars > > Actually, it looks to me that that's an argument for using is for > checking for null rather than ==, since == isn't really going to tell > you. The fact that == doesn't care about whether an array is null makes > it not work for checking for whether an array is null. I guess it depends on what behaviour you're after. In the present case, if you want chomp(a, null) and chomp(a, "") to do the same thing, then you should use '=='. If you want chomp(a, "") to simply do nothing, use 'is'. I just figured that the former was the desired behaviour here. If it isn't, I agree with you. :) > 1. As I understand it, using is instead of == is for all references, not > just arrays and their bizarre pseudo-null state. Using is with a class > will avoid calling opEquals() and does exactly what you want when > checking whether a class reference is null. Fun fact: Actually, 'is' works for any type. assert (1 is 1); As I've understood it, 'a is b' is true if the variables a and b contain the exact same bits. If a and b are value types, this must mean they have the same value, and if they are references (including arrays), it means they refer to the same data. > 2. For arrays, if you want to check whether it really is null, then you > _must_ use is, because == obviously isn't going to tell you. It'll just > lump empty arrays in with null ones. For instance, if you want to check > that an array has never been initialized or that it has been set to null > and never set to something else, then you need to use is. > > 3. On the other hand, if what you really care about is checking whether > an array has any elements and you don't care about whether it's null or > not, then the empty function/property would be the better way to go. > It's quite explicit, and it's more generic, doing things the way that > ranges are done. I totally agree with you. Lately, I have started using "empty" (as well as the other range primitives) for arrays myself. I just disagreed that 'is' would produce what I perceived to be the right behaviour for the function in question. But that perception may well be wrong. ;) > Personally, I think that the way that null is handled with arrays and > associative arrays is a poor design choice (if they're null, they should > be null until you assign to them with new rather than this whole null > but not null nonsense), but we're stuck with it I guess. There, I don't agree with you. Arrays are a sort of pseudo-reference type, so I don't mind 'null' being a sort of pseudo-null in that context. Actually, I find it to be quite elegant. It's a matter of taste, I guess. -Lars
Re: std.string.chomp error
On Tuesday 10 August 2010 00:30:37 Lars T. Kyllingstad wrote: > No, using 'is' won't work. Check this out: > > int[] a; > assert (a == null); > assert (a is null); > > a = new int[10]; > a.length = 0; > assert (a == null); > assert (a !is null); > > The thing is, '==' tests whether two arrays are equal, that is, that they > are equally long and that their elements are equal. Any empty array is > equal to null -- in fact, in this context 'null' is just a way of > denoting an empty array that doesn't point to any particular memory block > (i.e. hasn't been initialised yet). > > // This is what '==' does > bool mimicEquals(int[] a, int[] b) > { > if (a.length != b.length) return false; > foreach (i; 0 .. a.length) if (a[i] != b[i]) return false; > return true; > } > > 'is', on the other hand, tests whether two arrays are identical, i.e. > that they have the same length and *refer to the same piece of memory*. > > // This is (sort of) what 'is' does > bool mimicIs(int[] a, int[] b) > { > return (a.ptr == b.ptr && a.length == b.length); > } > > -Lars Actually, it looks to me that that's an argument for using is for checking for null rather than ==, since == isn't really going to tell you. The fact that == doesn't care about whether an array is null makes it not work for checking for whether an array is null. 1. As I understand it, using is instead of == is for all references, not just arrays and their bizarre pseudo-null state. Using is with a class will avoid calling opEquals() and does exactly what you want when checking whether a class reference is null. 2. For arrays, if you want to check whether it really is null, then you _must_ use is, because == obviously isn't going to tell you. It'll just lump empty arrays in with null ones. For instance, if you want to check that an array has never been initialized or that it has been set to null and never set to something else, then you need to use is. 3. On the other hand, if what you really care about is checking whether an array has any elements and you don't care about whether it's null or not, then the empty function/property would be the better way to go. It's quite explicit, and it's more generic, doing things the way that ranges are done. Personally, I think that the way that null is handled with arrays and associative arrays is a poor design choice (if they're null, they should be null until you assign to them with new rather than this whole null but not null nonsense), but we're stuck with it I guess. - Jonathan M Davis
Re: std.string.chomp error
On Mon, 09 Aug 2010 17:35:56 -0700, Jonathan M Davis wrote: > On Monday, August 09, 2010 17:09:03 simendsjo wrote: >> On 10.08.2010 02:09, Jonathan M Davis wrote: >> > On Monday, August 09, 2010 16:59:07 bearophile wrote: >> >> simendsjo: >> >>> Ahem.. :) Yes, I did miss your answer! How I got fooled by the >> >>> preview pane and never noticed the scrollbar. >> >> >> >> No problem, it happens, don't worry. >> >> >> >>> I cannot see how your other bug report relates to this though. >> >> >> >> My other bug report is about this line in your code: >> >> if (delimiter == null) >> >> >> >> I don't like it :-) >> >> >> >> Bye, >> >> bearophile >> > >> > Why, because it should be >> > >> > if(delimiter is null) >> > >> > >> > or just >> > >> > if(!delimiter) >> > >> > >> > - Jonathan M Davis >> >> Hehe.. You're a bit beyond my D level right now. At least I now know >> null == false and you can do reference is null :) > > IIRC, you're not really supposed to do "delim == null" but rather us > "delim is null" or shorten to to just "!delim". Why, I don't recall off > the top of my head, but it might be because "delim == null" would be > calling Object.opEquals(), and there's no need for that function call > (though fortunately "delim == null" translates to Object.opEquals(delim, > null) rather than delim.opEquals(null) which avoids issues where the lhs > is null and causes it to go boom). > > In either case, for null checks, I'd suggest either just using the > reference by itself or to explictly use "is null" if you want the extra > clarity. No, using 'is' won't work. Check this out: int[] a; assert (a == null); assert (a is null); a = new int[10]; a.length = 0; assert (a == null); assert (a !is null); The thing is, '==' tests whether two arrays are equal, that is, that they are equally long and that their elements are equal. Any empty array is equal to null -- in fact, in this context 'null' is just a way of denoting an empty array that doesn't point to any particular memory block (i.e. hasn't been initialised yet). // This is what '==' does bool mimicEquals(int[] a, int[] b) { if (a.length != b.length) return false; foreach (i; 0 .. a.length) if (a[i] != b[i]) return false; return true; } 'is', on the other hand, tests whether two arrays are identical, i.e. that they have the same length and *refer to the same piece of memory*. // This is (sort of) what 'is' does bool mimicIs(int[] a, int[] b) { return (a.ptr == b.ptr && a.length == b.length); } -Lars