www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - is ==

reply IntegratedDimensions <IntegratedDimensions gmail.com> writes:
Why does D complain when using == to compare with null? Is there 
really any technical reason? if one just defines == null to is 
null then there should be no problem. It seems like a pedantic 
move by who ever implemented it and I'm hoping there is actually 
a good technical reason for it.
May 18 2018
next sibling parent reply Uknown <sireeshkodali1 gmail.com> writes:
On Friday, 18 May 2018 at 23:53:12 UTC, IntegratedDimensions 
wrote:
 Why does D complain when using == to compare with null? Is 
 there really any technical reason? if one just defines == null 
 to is null then there should be no problem. It seems like a 
 pedantic move by who ever implemented it and I'm hoping there 
 is actually a good technical reason for it.
D only complains of this when you use ref types (classes or AAs). For e.g: --- test.d void main() { int * p; assert (p == null && p is null); class C { int x; } C c; assert (c is null); assert (c == null); //error, c is a reference, so there is confusion between opEquals and null check } ---
May 18 2018
parent IntegratedDimensions <IntegratedDimensions gmail.com> writes:
On Friday, 18 May 2018 at 23:58:18 UTC, Uknown wrote:
 On Friday, 18 May 2018 at 23:53:12 UTC, IntegratedDimensions 
 wrote:
 Why does D complain when using == to compare with null? Is 
 there really any technical reason? if one just defines == null 
 to is null then there should be no problem. It seems like a 
 pedantic move by who ever implemented it and I'm hoping there 
 is actually a good technical reason for it.
D only complains of this when you use ref types (classes or AAs). For e.g: --- test.d void main() { int * p; assert (p == null && p is null); class C { int x; } C c; assert (c is null); assert (c == null); //error, c is a reference, so there is confusion between opEquals and null check } ---
or pointers.
May 18 2018
prev sibling next sibling parent reply Neia Neutuladh <neia ikeran.org> writes:
On Friday, 18 May 2018 at 23:53:12 UTC, IntegratedDimensions 
wrote:
 Why does D complain when using == to compare with null? Is 
 there really any technical reason? if one just defines == null 
 to is null then there should be no problem. It seems like a 
 pedantic move by who ever implemented it and I'm hoping there 
 is actually a good technical reason for it.
tldr: this error is outdated. In the days of yore, "obj == null" would call "obj.opEquals(null)". Attempting to call a virtual method on a null object is a quick path to a segmentation fault. So "obj == null" would either yield false or crash your program. Except it's worse than that; your opEquals method had to explicitly check for null. So if your class had a custom equality function, "obj == null" was probably going to segfault no matter what. Because of this common source of errors, in DMD 2.012 (2008), we got an error only for the case of comparing with a literal null. (The compiler isn't a mind-reader; it doesn't know whether that variable will be null when that line of code executes.) This still sucked, so in 2015 we got a runtime function to handle object equality: https://github.com/dlang/druntime/blob/dff824eda422b1fcdde5f2fe53120fcd71733aaa/src/object.d#L140 But we haven't removed the error message. It *is* faster to call "foo is null" than "foo == null", but I don't think that's particularly worth a compiler error. The compiler could just convert it to "is null" automatically in that case. One casualty of the current state of affairs is that no object may compare equal to null.
May 18 2018
parent reply Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
On Saturday, May 19, 2018 01:27:59 Neia Neutuladh via Digitalmars-d-learn 
wrote:
 On Friday, 18 May 2018 at 23:53:12 UTC, IntegratedDimensions

 wrote:
 Why does D complain when using == to compare with null? Is
 there really any technical reason? if one just defines == null
 to is null then there should be no problem. It seems like a
 pedantic move by who ever implemented it and I'm hoping there
 is actually a good technical reason for it.
tldr: this error is outdated. In the days of yore, "obj == null" would call "obj.opEquals(null)". Attempting to call a virtual method on a null object is a quick path to a segmentation fault. So "obj == null" would either yield false or crash your program. Except it's worse than that; your opEquals method had to explicitly check for null. So if your class had a custom equality function, "obj == null" was probably going to segfault no matter what. Because of this common source of errors, in DMD 2.012 (2008), we got an error only for the case of comparing with a literal null. (The compiler isn't a mind-reader; it doesn't know whether that variable will be null when that line of code executes.) This still sucked, so in 2015 we got a runtime function to handle object equality: https://github.com/dlang/druntime/blob/dff824eda422b1fcdde5f2fe53120fcd717 33aaa/src/object.d#L140 But we haven't removed the error message.
Actually, that runtime function has existed since before TDPL came out in 2010. It even shows the implementation of the free function opEquals (which at the time was in object_.d rather than object.d). I'm not even sure that the error message was added before the free function version of opEquals was. Maybe when that error message was first introduced, it avoided a segfault, but if so, it has been a _long_ time since that was the case.
 It *is* faster to call "foo is null" than "foo == null", but I
 don't think that's particularly worth a compiler error. The
 compiler could just convert it to "is null" automatically in that
 case.

 One casualty of the current state of affairs is that no object
 may compare equal to null.
Honestly, while the compiler probably should just convert obj == null to obj is null, there really still isn't really a good reason to ever use == with null. It's _never_ better than using is, and in some cases, it's worse. Of course, the most notable case where using == with null is a terrible idea is dynamic arrays, and that's the case where the compiler _doesn't_ complain. Using == with null and arrays is always unclear about the programmer's intent and almost certainly wasn't what the programmer intended. If the programmer cares about null, they should use is. If they care about lengnth, then that's what they should check. Checking null with == is just a huge code smell. So, perhaps the compiler is being pedantic, but it's still telling you the right thing. It's just insisting about it in the case where it matters less while not complaining aobut it in the case where it really matters, which is dumb. So IMHO, if anything, adding an error message for the array case would make more sense than getting rid of the error with pointers and references. - Jonathan M Davis
May 18 2018
next sibling parent reply Neia Neutuladh <neia ikeran.org> writes:
On Saturday, 19 May 2018 at 01:48:38 UTC, Jonathan M Davis wrote:
 Actually, that runtime function has existed since before TDPL 
 came out in 2010. It even shows the implementation of the free 
 function opEquals (which at the time was in object_.d rather 
 than object.d). I'm not even sure that the error message was 
 added before the free function version of opEquals was. Maybe 
 when that error message was first introduced, it avoided a 
 segfault, but if so, it has been a _long_ time since that was 
 the case.
Good catch. I overly trusted git blame. The opEquals(Object, Object) function was added in February 2010, while the error message was added in March 2008.
 Of course, the most notable case where using == with null is a 
 terrible idea is dynamic arrays, and that's the case where the 
 compiler _doesn't_ complain. Using == with null and arrays is 
 always unclear about the programmer's intent and almost 
 certainly wasn't what the programmer intended. If the 
 programmer cares about null, they should use is. If they care 
 about lengnth, then that's what they should check. Checking 
 null with == is just a huge code smell.
I feel like the array == null version is more explicit about not allocating memory. However, I'm paranoid about whether that's going to check the pointer instead, so I mostly use array.length == 0 instead.
May 18 2018
parent reply Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
On Saturday, May 19, 2018 03:32:53 Neia Neutuladh via Digitalmars-d-learn 
wrote:
 Of course, the most notable case where using == with null is a
 terrible idea is dynamic arrays, and that's the case where the
 compiler _doesn't_ complain. Using == with null and arrays is
 always unclear about the programmer's intent and almost
 certainly wasn't what the programmer intended. If the
 programmer cares about null, they should use is. If they care
 about lengnth, then that's what they should check. Checking
 null with == is just a huge code smell.
I feel like the array == null version is more explicit about not allocating memory. However, I'm paranoid about whether that's going to check the pointer instead, so I mostly use array.length == 0 instead.
I'm not sure what memory allocations you're worried about. Neither "" nor [] allocates memory, but regardless, if you're looking to check whether arr.ptr is null, then that's effectively what you get with arr is null - though IIRC, it still checks length in that case. It's just that the type system guarantees that a null dynamic array has a length of 0. You'd have to do some pretty screwy system casting to have a null dynamic array with a length other than 0. But you can always do arr.ptr is null Regardless, if you're checking for null, then is does the job, and if what you care about is whether the array is empty, then that's what arr.length == 0 and arr.empty do. arr == null is just risking confusion, because there's no way to know if the programmer meant arr is null or arr.empty Regardless, it's absolutely guaranteed that arr == null is going to avoid checking the value of ptr just like arr == arr2 won't check ptr if length == 0. == only cares that both arrays have the same number of elements and that they're equal with ==. If length is 0, there's no need to check the elements to verify that, and if the lengths don't match, there's no need to check the elements. If you actually used enough screwed up casts to get two dynamic arrays whose ptr values were null, and they had different lengths, you still wouldn't get a crash. The _only_ way to get a segfault from using == with a null dynamic array is if you did enough screwy system casts to have two dynamic arrays with the same non-zero length, and one of them had a null ptr. It wouldn't even crash if they were both null, because it's going to check the ptrs before comparing the elements. Regardless, in no real program do you have to worry about segfaulting with == and dynamic arrays, and you don't have to worry about == ever allocating. The closest that you'd get to that would be if you compared against a non-null array literal. e.g. arr == [1, 2, 3] and if the compiler is smart enough, not even that should allocate (though I don't remember if it's that smart at the moment). Ultimately, the question of is vs == comes down to clarity of the programmer's intent. - Jonathan M Davis
May 18 2018
parent reply Neia Neutuladh <neia ikeran.org> writes:
On Saturday, 19 May 2018 at 04:30:24 UTC, Jonathan M Davis wrote:
 On Saturday, May 19, 2018 03:32:53 Neia Neutuladh via 
 Digitalmars-d-learn wrote:
 Of course, the most notable case where using == with null is 
 a terrible idea is dynamic arrays, and that's the case where 
 the compiler _doesn't_ complain. Using == with null and 
 arrays is always unclear about the programmer's intent and 
 almost certainly wasn't what the programmer intended. If the 
 programmer cares about null, they should use is. If they 
 care about lengnth, then that's what they should check. 
 Checking null with == is just a huge code smell.
I feel like the array == null version is more explicit about not allocating memory. However, I'm paranoid about whether that's going to check the pointer instead, so I mostly use array.length == 0 instead.
I'm not sure what memory allocations you're worried about. Neither "" nor [] allocates memory
"" is syntax for compile-time constants and shouldn't ever allocate. [] is a specific case of [values...]; the general case allocates, but this one case does not. null is not even a compile-time constant; it's a value baked into the language and is guaranteed not to allocate.
 but regardless, if you're looking to check whether arr.ptr is 
 null, then that's effectively what you get with

 arr is null
I don't think I've ever wanted to distinguish a zero-length slice of an array from a null array.
 Regardless, if you're checking for null, then is does the job, 
 and if what you care about is whether the array is empty, then 
 that's what

 arr.length == 0

 and

 arr.empty

 do.
As I already said, I use "array.length == 0". "array.empty" is part of that newfangled range business.
May 19 2018
parent Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
On Saturday, May 19, 2018 17:13:36 Neia Neutuladh via Digitalmars-d-learn 
wrote:
 I don't think I've ever wanted to distinguish a zero-length slice
 of an array from a null array.
It's safer if you don't, because it's so easy to end up with a dynamic array that is empty instead of null, and stuff like == doesn't care about the difference. But there is code that's written that cares (e.g. IIRC, std.experimental.allocator does in some cases). if(arr) is equivalent to if(cast(bool)arr) and casting a dynamic array to bool is equivalent to arr !is null which means that if(arr) means if(arr !is null) whereas it's not uncommon for folks to think that it means if(arr.length != 0) Similarly, assert(arr); is ultimately equivalent to asser(arr !is null); which suprises many folks and is rarely what folks want. So, there was a push at one point to make it illegal to use a dynamic array in an if statment or assertion directly, and it did briefly make it into the compiler. However, a few folks (Andrei and Vladimir in particular IIRC), had used arrays in if statments directly quite a bit, knowing full well what it meant. So, their code was right (albeit potentially confusing), and they pushed back. So, the change was reverted, and we're still stuck with the error-prone situation that we've had. So, most of us would argue that it's risky to treat null dynamic arrays as special and that it should be done with caution, but programmers who know what they're definitely do it. Unfortunately, when you read code that's writen that way, it's usually hard to tell whether it was written with that undertanding or not, and a stray == in the code could easily break it.
 As I already said, I use "array.length == 0". "array.empty" is
 part of that newfangled range business.
LOL. Well, if you stay away from ranges, you're losing out on a lot of benefits - including large portions of the standard library, but checking for length works fine if you're dealing with code that's just using dynamic arrays and not ranges. The key thing is to avoid arr == null, because that's were the bugs lie. - Jonathan M Davis
May 19 2018
prev sibling parent reply Steven Schveighoffer <schveiguy yahoo.com> writes:
On 5/18/18 9:48 PM, Jonathan M Davis wrote:
 On Saturday, May 19, 2018 01:27:59 Neia Neutuladh via Digitalmars-d-learn
 wrote:
 On Friday, 18 May 2018 at 23:53:12 UTC, IntegratedDimensions

 wrote:
 Why does D complain when using == to compare with null? Is
 there really any technical reason? if one just defines == null
 to is null then there should be no problem. It seems like a
 pedantic move by who ever implemented it and I'm hoping there
 is actually a good technical reason for it.
tldr: this error is outdated. In the days of yore, "obj == null" would call "obj.opEquals(null)". Attempting to call a virtual method on a null object is a quick path to a segmentation fault. So "obj == null" would either yield false or crash your program.
I remember this, and I remember arguing for the current behavior many times (after having many many crashes) :) https://forum.dlang.org/post/fqlgah$15v2$1 digitalmars.com Read that thread if you want to see the rationale. However, I'd argue it's still good to keep the error as there is literally no point to not using == null on class references vs. is null. You now would get the same result, but it's faster/cleaner.
 Actually, that runtime function has existed since before TDPL came out in
 2010. It even shows the implementation of the free function opEquals (which
 at the time was in object_.d rather than object.d). I'm not even sure that
 the error message was added before the free function version of opEquals
 was. Maybe when that error message was first introduced, it avoided a
 segfault, but if so, it has been a _long_ time since that was the case.
Some things in TDPL were forward-thinking. I remember Andrei fleshing out some of how the languages SHOULD behave in the forums or mailing lists for the purposes of writing TDPL even though it didn't yet behave that way. In fact, I'm almost positive the new object comparison function came as a result of TDPL (but I'm not 100% sure). Some of TDPL still has never been implemented. Long story short, don't date the existence of features in TDPL based on the publication :) In this case, for fun (what is wrong with me), I looked up the exact date it got added, and it was Feb 2010: https://github.com/dlang/druntime/commit/2dac6aa262309e75ad9b5 4cb4d1c3c1f0ecc2ae. TDPL came out in June 2010, so this feature does predate TDPL by a bit. In fact, through this exercise, I just noticed that the reason it returns auto instead of bool is to make sure it gets into the now defunct "generated" object.di file (https://github.com/dlang/druntime/pull/2190).
 It *is* faster to call "foo is null" than "foo == null", but I
 don't think that's particularly worth a compiler error. The
 compiler could just convert it to "is null" automatically in that
 case.
It's not worth a compiler error if we didn't already have it, but I don't know that it's worth taking out. It's really what you should be doing, it's just that the penalty for not doing it isn't as severe as it used to be.
 One casualty of the current state of affairs is that no object
 may compare equal to null.
And let's keep it that way!
 Of
 course, the most notable case where using == with null is a terrible idea is
 dynamic arrays, and that's the case where the compiler _doesn't_ complain.
I use arr == null all the time. I'm perfectly fine with that, and understand what it means.
 Using == with null and arrays is always unclear about the programmer's
 intent and almost certainly wasn't what the programmer intended.
I beg to differ.
 If the
 programmer cares about null, they should use is. If they care about lengnth,
 then that's what they should check. Checking null with == is just a huge
 code smell.
IMO, doing anything based on the pointer of an array being null is a huge code smell. In which case, == null is perfectly acceptable. I'm comparing my array to an empty array. What is confusing about that? I actually hate using the pointer in any aspect -- an array is semantically equivalent to its elements, it's not important where it's allocated. The only place D forces me to care about the pointer is when I'm dealing with ranges.
 So, perhaps the compiler is being pedantic, but it's still telling you the
 right thing. It's just insisting about it in the case where it matters less
 while not complaining aobut it in the case where it really matters, which is
 dumb. So IMHO, if anything, adding an error message for the array case would
 make more sense than getting rid of the error with pointers and references.
I hope this never happens. -Steve
May 21 2018
parent reply Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
On Monday, May 21, 2018 10:01:15 Steven Schveighoffer via Digitalmars-d-
learn wrote:
 On 5/18/18 9:48 PM, Jonathan M Davis wrote:
 Of
 course, the most notable case where using == with null is a terrible
 idea is dynamic arrays, and that's the case where the compiler
 _doesn't_ complain.
I use arr == null all the time. I'm perfectly fine with that, and understand what it means.
 Using == with null and arrays is always unclear about the programmer's
 intent and almost certainly wasn't what the programmer intended.
I beg to differ.
 If the
 programmer cares about null, they should use is. If they care about
 lengnth, then that's what they should check. Checking null with == is
 just a huge code smell.
IMO, doing anything based on the pointer of an array being null is a huge code smell. In which case, == null is perfectly acceptable. I'm comparing my array to an empty array. What is confusing about that? I actually hate using the pointer in any aspect -- an array is semantically equivalent to its elements, it's not important where it's allocated. The only place D forces me to care about the pointer is when I'm dealing with ranges.
The core problem here is that no one reading a piece of code has any way of knowing whether the programmer knew what they were doing or not when using == null with an array, and the vast majority of newbies are not going to have understood the semantics properly. If I know that someone like you or Andrei wrote the code, then the odds are good that what the code does is exactly what you intended. But for the average D programmer? I don't think that it makes any sense to assume that, especially since anyone coming from another language is going to assume that == null is checking for null, when it's not. It's the same reason that if(arr) was temporarily out of the language. The odds are very high that the programmer using it is using it wrong. Andrei and Vladimir were using it correctly in their code, so they didn't like the fact that it had then become illegal, but while knew what they were doing and were using it correctly, plenty of other folks have been inserting bugs whenever they do that, and if I see if(arr) or assert(arr) in code, I'm going to consider it to be code smell just as much as I consider arr == null to be code smell. And yes, trying to treat the ptr as being null as special with a dynamic array is risky, and most code shouldn't be doing it, but you're almost forced to in some cases when interacting with C code, and clearly there are folks that do (e.g. Andrei and Vladimir). But even if we could unequivocably say that no one should be doing it, you still have no way of knowing whether someone is attempting it or not when they do arr == null, and since caring whether an array is null or not is a very typical thing to do in other languages where there is a very clear distinction between a null array and an empty one, plenty of folks come to D expecting to be able to do the same. And they're going to write arr == null or arr != null, and any time I see code like that, I'm going to have sit down and figure out whether they really meant arr is null, or whether they meant arr.length == 0, whereas if they had just written arr is null or arr.length == 0 (or arr.empty), their intent would have been perfectly clear. As such, I would strongly advise D programmers to use arr.empty or arr.length == 0 instead of arr == null, even if they know what they're doing, just like I would advise them to not treat null as special for arrays unless they really need to. At this point, I'm honestly inclined to think that we never should have allowed null for arrays. We should have taken the abstraction a bit further and disallowed using null to represent dynamic arrays. It would then presumably still work to do arr.ptr is null, but arr is null wouldn't work, because null wouldn't be an array, and arr == null definitely wouldn't work. Then we could just use [] for empty arrays everywhere, and there would be no confusion, leaving null for actual pointers. And it would almost certinly kill off all of the cases where null was treated as special for dynamic arrays except maybe for when dealing with C code, but in that case, they'd have to use ptr directly. However, at this point, I expect that that's all water under the bridge, and we're stuck with it. - Jonathan M Davis
May 21 2018
parent reply Steven Schveighoffer <schveiguy yahoo.com> writes:
On 5/21/18 2:05 PM, Jonathan M Davis wrote:
 The core problem here is that no one reading a piece of code has any way of
 knowing whether the programmer knew what they were doing or not when using
 == null with an array, and the vast majority of newbies are not going to
 have understood the semantics properly. If I know that someone like you or
 Andrei wrote the code, then the odds are good that what the code does is
 exactly what you intended. But for the average D programmer? I don't think
 that it makes any sense to assume that, especially since anyone coming from
 another language is going to assume that == null is checking for null, when
 it's not.
For me, the code smell is using arr is null (is it really necessary to check for a null pointer here?), for which I always have to look at more context to see if it's *really* right. Even people who write == null may want to check for null thinking that it's how you check an array is empty, not realizing that it *doesn't* check for a null pointer, *AND* it still does exactly what they need it to do ;)
 
 It's the same reason that
 
 if(arr)
 
 was temporarily out of the language.
It's similar, but I consider it a different reason. While the intent of == null may not be crystal clear, 99% of people don't care about the pointer, they just care whether it's empty. So the default case is usually good enough, even if you don't know the true details. Whereas, if(arr) is checking that the pointer is null as well as the length is 0. Most people aren't expecting that, and those who are are like Andrei and Vladimir -- they know the quirks of the language here. For the longest time I thought it was just checking the pointer! I think aside from the clout of the ones who wanted it, the biggest reason that change was reverted was that it became really difficult to use an array inside a conditional. One-liners had to be extracted out, temporary variables defined.
 At this point, I'm honestly inclined to think that we never should have
 allowed null for arrays. We should have taken the abstraction a bit further
 and disallowed using null to represent dynamic arrays. It would then
 presumably still work to do arr.ptr is null, but arr is null wouldn't work,
 because null wouldn't be an array, and arr == null definitely wouldn't work.
 Then we could just use [] for empty arrays everywhere, and there would be no
 confusion, leaving null for actual pointers. And it would almost certinly
 kill off all of the cases where null was treated as special for dynamic
 arrays except maybe for when dealing with C code, but in that case, they'd
 have to use ptr directly. However, at this point, I expect that that's all
 water under the bridge, and we're stuck with it.
If we never had null be the default value for an array, and used [] instead, I would be actually OK with that. I also feel one of the confusing things for people coming to the language is that arrays are NOT exactly reference types, even though null can be used as a value for assignment or comparison. But it still wouldn't change what most people write or mean, they just would write == [] instead of == null. I don't see how this would solve any of your concerns. -Steve
May 21 2018
parent reply Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
On Monday, May 21, 2018 14:40:24 Steven Schveighoffer via Digitalmars-d-
learn wrote:
 On 5/21/18 2:05 PM, Jonathan M Davis wrote:
 The core problem here is that no one reading a piece of code has any way
 of knowing whether the programmer knew what they were doing or not when
 using == null with an array, and the vast majority of newbies are not
 going to have understood the semantics properly. If I know that someone
 like you or Andrei wrote the code, then the odds are good that what the
 code does is exactly what you intended. But for the average D
 programmer? I don't think that it makes any sense to assume that,
 especially since anyone coming from another language is going to assume
 that == null is checking for null, when it's not.
For me, the code smell is using arr is null (is it really necessary to check for a null pointer here?), for which I always have to look at more context to see if it's *really* right.
Really? I would never expect anyone to use is unless they really cared about whether array was null. I'd be concerned about whether the code in general was right, because treating null as special gets tricky, but that particular line wouldn't concern me.
 Even people who write == null may want to check for null thinking that
 it's how you check an array is empty, not realizing that it *doesn't*
 check for a null pointer, *AND* it still does exactly what they need it
 to do ;)
You honestly expect someone first coming to D expect to check whether an array is empty by checking null? That's a bizarre quirk of D that I have never seen anyhwere else. I would never expect anyone to purposefully use == null to check for empty unless they were very familiar with D, and even then, I'd normally expect them to ask what they really mean, which is whether the array is empty.
 It's the same reason that

 if(arr)

 was temporarily out of the language.
It's similar, but I consider it a different reason. While the intent of == null may not be crystal clear, 99% of people don't care about the pointer, they just care whether it's empty. So the default case is usually good enough, even if you don't know the true details.
I think that that's the key point of disagreement here. I would never consider the intent of == null to be crystal clear based solely on the code, because it is so common outside of D to use == null to actually check for null, and there are better ways in D to check for empty if that's what you really mean. My immediate expectation on seeing arr == null is that the programmer does not properly understand arrays in D. If I knew that someone like you wrote the code, I'd probably decide that you knew what you were doing and didn't make a mistake, but I'm not going to assume that in general, and honestly, I would consider it bad coding practice (though we obviously disagree on that point). I would consider the if(arr) and arr == null cases to be exactly the same. They both are red flags that the person in question does not understand how arrays in D work. Yes, someone who knows what they're doing may get it right, but I'd consider both to be code smells and I wouldn't purposefully do either in my own code. If I found either in my own code, I would expect that I'd just found a careless bug.
 At this point, I'm honestly inclined to think that we never should have
 allowed null for arrays. We should have taken the abstraction a bit
 further and disallowed using null to represent dynamic arrays. It would
 then presumably still work to do arr.ptr is null, but arr is null
 wouldn't work, because null wouldn't be an array, and arr == null
 definitely wouldn't work. Then we could just use [] for empty arrays
 everywhere, and there would be no confusion, leaving null for actual
 pointers. And it would almost certinly kill off all of the cases where
 null was treated as special for dynamic arrays except maybe for when
 dealing with C code, but in that case, they'd have to use ptr directly.
 However, at this point, I expect that that's all water under the
 bridge, and we're stuck with it.
If we never had null be the default value for an array, and used [] instead, I would be actually OK with that. I also feel one of the confusing things for people coming to the language is that arrays are NOT exactly reference types, even though null can be used as a value for assignment or comparison. But it still wouldn't change what most people write or mean, they just would write == [] instead of == null. I don't see how this would solve any of your concerns.
It would solve the concern, because no one is going to write arr == [] to check for null. They'de write it just like they'd write arr == "". They're clearly checking for empty, not null. The whole problem here is that pretty much everywhere other than D arrays, null and empty are two separate things, and pretty much anyone coming from another language will expect them to be different. It wouldn't surprise me at all to see a newbie D programmer doing something like if(arr != null && arr == arr2) {...} I would never expect anyone coming from another language to use arr == null with the idea that it's actually checking for null, and given how confusing dynamic arrays are for many people, it wouldn't surprise me for someone who has programmed in D for a while to not properly understand the situation. At some point, they learn, but it's clearly one of those topics that confuses pretty much everyone at first. And out of those who do understand how D dynamic arrays work, a number of them continue to distinguish between null and empty arrays in their code - e.g. folks like Andrei and Vladimir who write code that uses if(arr) and means it the way the language means it. The core problem is that D treats null arrays as empty. If it would either treat them as actually null (with all of the segfaults that go with that) or not treat null as a dynamic array, then that whole problem goes away. So, if null were not a dynamic array in any shape or form, and you had to use [] to indicate an empty array, then that would solve my main concerns with null and dynamic arrays. Now, that then leaves the issue of folks accessing ptr and treating null as special there, but if you had to actually access ptr to do that, I suspect that the practice of treating null arrays as special would go away. But even if it didn't, the cases where someone was trying to do that would then be clear, because they'd have to access ptr directly, so it would almost certainly be something that only folks who knew what they were doing would do much with, whereas arr == null is something that pretty much any D newbie is going to try and screw up. - Jonathan M Davis
May 21 2018
parent Steven Schveighoffer <schveiguy yahoo.com> writes:
On 5/21/18 3:20 PM, Jonathan M Davis wrote:
 On Monday, May 21, 2018 14:40:24 Steven Schveighoffer via Digitalmars-d-
 learn wrote:
 For me, the code smell is using arr is null (is it really necessary to
 check for a null pointer here?), for which I always have to look at more
 context to see if it's *really* right.
Really? I would never expect anyone to use is unless they really cared about whether array was null. I'd be concerned about whether the code in general was right, because treating null as special gets tricky, but that particular line wouldn't concern me.
Don't get me wrong, they probably *do* mean to check if it's null. But do they *need* to check? I'll borrow from your example below: if(arr != null && arr == arr2) Replace this with: if(arr !is null && arr == arr2) Does this look any better? I don't think so, it means the person didn't understand what an array actually is. Even though the second actually has some semantic meaning (the first is a no-op), it's likely not what the author intended. In most cases, when they check for null, they just want to check to see if the array is unset. The semantic meaning of this is usually that it's empty, they don't really care if it's actually null or not. In which case, checking for exact nullness is actually more expensive, and prone to problems. This comes from many languages where an array is an object type that defaults to null, and we reinforce that misconception by allowing null as a valid array literal.
 Even people who write == null may want to check for null thinking that
 it's how you check an array is empty, not realizing that it *doesn't*
 check for a null pointer, *AND* it still does exactly what they need it
 to do ;)
You honestly expect someone first coming to D expect to check whether an array is empty by checking null? That's a bizarre quirk of D that I have never seen anyhwere else. I would never expect anyone to purposefully use == null to check for empty unless they were very familiar with D, and even then, I'd normally expect them to ask what they really mean, which is whether the array is empty.
Reread what I said again. They *think* they need to check if it's null (it being the mythical Array object type that the language no doubt they only need to check if it's empty. Which happens to be all they really need. For instance: int[] arr; if (cond) { ... arr = new int[5]; ... } if (arr == null) Now, you can certainly replace arr == null with arr is null, and the code works fine -- identically, even though it's more expensive. But to me, the arr is null is a red flag. Does the person know that they are checking for the ACTUAL value null? You still have to read the code to figure it out! I would say most times it's a bug waiting to happen. I can't imagine you just see "arr is null" and move on believing the author knew what they were doing.
 It's the same reason that

 if(arr)

 was temporarily out of the language.
It's similar, but I consider it a different reason. While the intent of == null may not be crystal clear, 99% of people don't care about the pointer, they just care whether it's empty. So the default case is usually good enough, even if you don't know the true details.
I think that that's the key point of disagreement here. I would never consider the intent of == null to be crystal clear based solely on the code, because it is so common outside of D to use == null to actually check for null, and there are better ways in D to check for empty if that's what you really mean. My immediate expectation on seeing arr == null is that the programmer does not properly understand arrays in D. If I knew that someone like you wrote the code, I'd probably decide that you knew what you were doing and didn't make a mistake, but I'm not going to assume that in general, and honestly, I would consider it bad coding practice (though we obviously disagree on that point).
The fundamental reason why == null is generally OK is because generally the person doesn't distinguish between nullness and non-null but empty. Believe it or not, this is my position as well. Either works fine for their code, and in fact, when you analyze the code, checking for emptiness is really what they mean. Consider that new T[0] returns a null array. What happens if it returned a non-null array? Only code that uses "is null" would break. Code that uses == null would work fine.
 I would consider the if(arr) and arr == null cases to be exactly the same.
 They both are red flags that the person in question does not understand how
 arrays in D work. Yes, someone who knows what they're doing may get it
 right, but I'd consider both to be code smells and I wouldn't purposefully
 do either in my own code. If I found either in my own code, I would expect
 that I'd just found a careless bug.
== null is way more forgiving than if(arr). That is the point I'm making. Both can be used incorrectly, only one is going to have big problems with implementation details.
 If we never had null be the default value for an array, and used []
 instead, I would be actually OK with that. I also feel one of the
 confusing things for people coming to the language is that arrays are
 NOT exactly reference types, even though null can be used as a value for
 assignment or comparison.

 But it still wouldn't change what most people write or mean, they just
 would write == [] instead of == null. I don't see how this would solve
 any of your concerns.
It would solve the concern, because no one is going to write arr == [] to check for null. They'de write it just like they'd write arr == "".
I disagree. I think that's exactly what they would write, either that or arr == arr.init. I'd posit that most people who write == null are checking to see if an array has been initialized or not. Initialized meaning "I assigned some length of elements to it". This works whether the pointer is null or not.
 They're
 clearly checking for empty, not null. The whole problem here is that pretty
 much everywhere other than D arrays, null and empty are two separate things,
 and pretty much anyone coming from another language will expect them to be
 different. It wouldn't surprise me at all to see a newbie D programmer doing
 something like
 
 if(arr != null && arr == arr2)
 {...}
This is actually WAY easier to understand than just arr != null by itself. Clearly the user thinks arr is an object as I discussed above. It's not concerning at all, you just say "you don't need to check for null, it's not really an object".
 And out of those who do understand how D dynamic arrays work, a number of
 them continue to distinguish between null and empty arrays in their code -
 e.g. folks like Andrei and Vladimir who write code that uses
 
 if(arr)
 
 and means it the way the language means it. The core problem is that D
 treats null arrays as empty. If it would either treat them as actually null
 (with all of the segfaults that go with that) or not treat null as a dynamic
 array, then that whole problem goes away. So, if null were not a dynamic
 array in any shape or form, and you had to use [] to indicate an empty
 array, then that would solve my main concerns with null and dynamic arrays.
Code that uses if(arr) is prone to issues, because something that returns an empty array that has a null pointer is really an implementation detail. I wouldn't consider any code that depends on the implementation detail to be robust. If we couldn't use null, and used [], then it doesn't *look* as incorrect, and probably this would solve some of the confusion. But really, it's no different, and I'm sure you'd still see code like: if(arr != [] && arr == arr2) -Steve
May 21 2018
prev sibling parent reply Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
On Friday, May 18, 2018 23:53:12 IntegratedDimensions via Digitalmars-d-
learn wrote:
 Why does D complain when using == to compare with null? Is there
 really any technical reason? if one just defines == null to is
 null then there should be no problem. It seems like a pedantic
 move by who ever implemented it and I'm hoping there is actually
 a good technical reason for it.
Because == is pretty much never what you want to do with null. How much it matters depends on the types involved, but if you really want to check for null, is is definitely the right thing to use. In the case of pointers and references, is checks that they're pointing to the same thing. So, foo is null directly checks whether the reference or pointer is null. On the other hand, if you use ==, it's calling some form of opEquals. For pointers, that should generate identical code, but for class references, it means calling the free function opEquals. That function will check whether the references are null before calling opEquals on either of the class objects, but it does add unnecessary overhead (which, as I understand it, the compiler is unfortunately not currently able to optimize away) and provides no benefit over checking with is. Now, where is vs == _really_ matters (but unfortunately, the compiler does not complain about) is with dynamic arrays. If you do arr is null then the compiler will check whether the array's ptr is null. So, something like "" is null would be false. However, if you use ==, then it compares the length of the array and then only compares the ptrs if the length is non-zero. So, "" == null is true. So, with dynamic arrays, using == with null is a huge code smell. It _may_ be exactly what the programmer intends, but the odds are pretty high that they just don't properly understand the difference between is and ==, and they meant to be checking whether the array was actually null but just ended up checking whether its length was zero (which won't matter for some code but will cause subtle bugs in any code that treats null as special - e.g. if that is used to indicate that the array had not been given a value). Now, because of how == treats null like empty, it _is_ a bit risky to try and treat null as special with arrays, but anyone wanting to be clear in their code should either be checking null with is (in which case, they clearly care about null and not empty), or if they care about length == 0, they should either be calling empty on the array or explicitly checking the array's length, since that's what they care about. Much as having == work with null arrays avoids issues with segfaults due to an array be unitialized as well as avoids needing to give memory to an array just to have it be empty, you pretty much never actually care whether an array == null. You either care that its ptr is null (in which case, is checks that), or you care about whether its length is 0 (in which case empty or directly checking length checks that). arr == null is just unclear and likely buggy. So really, there are _zero_ advantages to comparing null with ==. Using == with null risks adding extra overhead, and it often makes the code less clear. On the other hand, using is makes it crystal clear what you mean and then does exactly what you mean - check whether the variable is actually null. So, maybe the compiler is being a bit pedantic by insisting that you use is rather than ==, but you really should be using is and not == when checking for null. - Jonathan M Davis
May 18 2018
parent reply IntegratedDimensions <IntegratedDimensions gmail.com> writes:
On Saturday, 19 May 2018 at 01:31:38 UTC, Jonathan M Davis wrote:
 On Friday, May 18, 2018 23:53:12 IntegratedDimensions via 
 Digitalmars-d- learn wrote:
 Why does D complain when using == to compare with null? Is 
 there really any technical reason? if one just defines == null 
 to is null then there should be no problem. It seems like a 
 pedantic move by who ever implemented it and I'm hoping there 
 is actually a good technical reason for it.
Because == is pretty much never what you want to do with null. How much it matters depends on the types involved, but if you really want to check for null, is is definitely the right thing to use. In the case of pointers and references, is checks that they're pointing to the same thing. So, foo is null directly checks whether the reference or pointer is null. On the other hand, if you use ==, it's calling some form of opEquals. For pointers, that should generate identical code, but for class references, it means calling the free function opEquals. That function will check whether the references are null before calling opEquals on either of the class objects, but it does add unnecessary overhead (which, as I understand it, the compiler is unfortunately not currently able to optimize away) and provides no benefit over checking with is. Now, where is vs == _really_ matters (but unfortunately, the compiler does not complain about) is with dynamic arrays. If you do arr is null then the compiler will check whether the array's ptr is null. So, something like "" is null would be false. However, if you use ==, then it compares the length of the array and then only compares the ptrs if the length is non-zero. So, "" == null is true. So, with dynamic arrays, using == with null is a huge code smell. It _may_ be exactly what the programmer intends, but the odds are pretty high that they just don't properly understand the difference between is and ==, and they meant to be checking whether the array was actually null but just ended up checking whether its length was zero (which won't matter for some code but will cause subtle bugs in any code that treats null as special - e.g. if that is used to indicate that the array had not been given a value). Now, because of how == treats null like empty, it _is_ a bit risky to try and treat null as special with arrays, but anyone wanting to be clear in their code should either be checking null with is (in which case, they clearly care about null and not empty), or if they care about length == 0, they should either be calling empty on the array or explicitly checking the array's length, since that's what they care about. Much as having == work with null arrays avoids issues with segfaults due to an array be unitialized as well as avoids needing to give memory to an array just to have it be empty, you pretty much never actually care whether an array == null. You either care that its ptr is null (in which case, is checks that), or you care about whether its length is 0 (in which case empty or directly checking length checks that). arr == null is just unclear and likely buggy. So really, there are _zero_ advantages to comparing null with ==. Using == with null risks adding extra overhead, and it often makes the code less clear. On the other hand, using is makes it crystal clear what you mean and then does exactly what you mean - check whether the variable is actually null. So, maybe the compiler is being a bit pedantic by insisting that you use is rather than ==, but you really should be using is and not == when checking for null. - Jonathan M Davis
I don't see your point. You claim that one should never use == null for whatever reason and that it is "wrong". So, why are you allowing wrong things in a language that can easily be fixed? Just reinterpret == null as is null and be done with it! This fixes the wrong and everyone can live happily ever after. Your logic is the same how people "ban" certain words like faggot. They don't like them for some reason, decide that no one should use it any more, and create a new word that essentially means the same thing... and it results in a loop where that new word then eventually gets "banned". == vs is might not be quite as extreme, maybe is will be the final "word". But if == null is banned by the compiler why the hell not just reinterpret to mean is null internally and be done with it and allow the syntax since it is so common? The only pitfalls is pasting code from other languages that might have a different interpretation, but those problems always exist since the languages are different. Your reasons for arrays is not good enough. First, not all types are arrays so you are banning a whole class of valid types for one case. That case, you say, is almost never meant anyways(that is, using == null is really meant as is null). So, ultimately what I feels like is that you are actually arguing for == null to be interpreted as is null but you don't realize it yet.
May 19 2018
parent reply Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
On Saturday, May 19, 2018 17:50:50 IntegratedDimensions via Digitalmars-d-
learn wrote:
 So, ultimately what I feels like is that you are actually arguing
 for == null to be interpreted as is null but you don't realize it
 yet.
Not really, no. Having foo == null be rewritten to foo is null in the non-dynamic array cases should be fine except for the fact that it's then a terrible habit to be in when you then have to deal with dynamic arrays. Using foo == null with dyanmic arrays is an enormous code smell, because the odds are extemely high that the programmer thinks that they're checking if the dynamic array is null when that's not what they're doing at all. IMHO, it should definitely be an error to use == with null and dynamic arrays because it is such a big code smell. Either the code should be using is to check whether the array is null, or it should be checking length. It should never be using == with null. But unfortunately, the compiler is completely backwards about this and treats it as an error with pointers and references but allows it with dynamic arrays. If the compiler were improved to just replace == with is in the cases that it currently treats as illegal, then that would be fine if it then treated it as illegal with dynamic arrays. But as it stands, it is still more efficient to use is with call references, so encouraging the programmer to use is is benefical, and it encourages the programmer to get in the habit of not using == with null, since it's a terrible habit to be in with dynamic arrays. But actually making it illegal for dynamic arrays would be a much better approach. If it were up to me, it would just be illgal to use == with null in general, because that's really the way it should be with dynamic arrays, and then the language would be consistent about it. But instead, the compiler screams in the case that matters far less and allows it in the case that is clearly bad. So, it's inconsistent in a dumb way. At least if it were inconsistent by allowing it for pointers and references while disallowing it for arrays, it would be prventing it in the case that truly matters, but instead, what we have is just dumb. - Jonathan M Davis
May 19 2018
parent reply IntegratedDimensions <IntegratedDimensions gmail.com> writes:
On Sunday, 20 May 2018 at 00:19:28 UTC, Jonathan M Davis wrote:
 On Saturday, May 19, 2018 17:50:50 IntegratedDimensions via 
 Digitalmars-d- learn wrote:
 So, ultimately what I feels like is that you are actually 
 arguing for == null to be interpreted as is null but you don't 
 realize it yet.
Not really, no. Having foo == null be rewritten to foo is null in the non-dynamic array cases should be fine except for the fact that it's then a terrible habit to be in when you then have to deal with dynamic arrays. Using foo == null with dyanmic arrays is an enormous code smell, because the odds are extemely high that the programmer thinks that they're checking if the dynamic array is null when that's not what they're doing at all. IMHO, it should definitely be an error to use == with null and dynamic arrays because it is such a big code smell. Either the code should be using is to check whether the array is null, or it should be checking length. It should never be using == with null. But unfortunately, the compiler is completely backwards about this and treats it as an error with pointers and references but allows it with dynamic arrays. If the compiler were improved to just replace == with is in the cases that it currently treats as illegal, then that would be fine if it then treated it as illegal with dynamic arrays. But as it stands, it is still more efficient to use is with call references, so encouraging the programmer to use is is benefical, and it encourages the programmer to get in the habit of not using == with null, since it's a terrible habit to be in with dynamic arrays. But actually making it illegal for dynamic arrays would be a much better approach. If it were up to me, it would just be illgal to use == with null in general, because that's really the way it should be with dynamic arrays, and then the language would be consistent about it. But instead, the compiler screams in the case that matters far less and allows it in the case that is clearly bad. So, it's inconsistent in a dumb way. At least if it were inconsistent by allowing it for pointers and references while disallowing it for arrays, it would be prventing it in the case that truly matters, but instead, what we have is just dumb. - Jonathan M Davis
Let D be a dynamic array, O a pointer or object: | Conceptually | in D D == null Invalid Valid D is null Valid Valid O == null Valid Invalid O is null Valid Valid Right? So what you are saying is you want to create 2 more invalids in the table to satisfy some weird logic which requires the programmer to remember special cases rather than make them all valid and easy to remember even though it can be done and make sense. In fact, the 2nd invalid makes sense and should be allowed so really you want to create 3 invalids for the price of one. Simply require == null as is null and be done with it. You can't police programmers minds and get them to program correctly. If you had a kid, do you box them up in a bubble room and not let them play because they might hurt themselves? How people learn is by making mistakes. It is better to provide a logical foundation that is consistent rather than produce corner cases to handle some corner case that was created to handle another corner case because someone handled a corner case.
May 19 2018
parent reply Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
On Sunday, May 20, 2018 01:51:50 IntegratedDimensions via Digitalmars-d-
learn wrote:
 Simply require == null as is null and be done with it.
That would be flat out wrong for dynamic arrays, because then auto result = arr == null and int[] nullArr; auto result = arr == nullArr; would have different semantics. The way that dynamic arrays are designed to work even if they're null mucks with this considerably here.
 You can't police programmers minds and get them to program correctly.
That's true, but making things that are highly likely to be wrong illegal prevents bugs. e.g. while(cond); is illegal in D precisely because it's error-prone. There are cases where doing something like that would be perfectly correct. e.g. while(++a != b); but you can do the exact same thing with empty parens while(++a != b) {} and all of those bugs with accidentally closing a loop with a semicolon go away, and you don't lose any expressiveness. The compiler just forces you to write it in a way that's far less error-prone. Making it illegal to compare the null literal with == also prevents bug, and you don't lose any expressiveness doing it either. It's the same kind of logic. Making error-prone constructs illegal when there's a simple equivalent that isn't error-prone is good language design, because it prevents bugs without actually restricting the programmer. It's when the language starts disallowing things that aren't error-prone and/or don't have simple equivalents that you start running into problems with the compiler getting in your way and treating you like a kid. For simple stuff like this, it ultimately saves you time and effort without getting in your way. At most, you occasionally have to replace foo == null with foo is null or foo.length != 0, and it potentially saves you hours of effort tracking down a subtle bug. - Jonathan M Davis
May 19 2018
parent reply IntegratedDimensions <IntegratedDimensions gmail.com> writes:
On Sunday, 20 May 2018 at 02:09:47 UTC, Jonathan M Davis wrote:
 On Sunday, May 20, 2018 01:51:50 IntegratedDimensions via 
 Digitalmars-d- learn wrote:
 Simply require == null as is null and be done with it.
That would be flat out wrong for dynamic arrays, because then auto result = arr == null and int[] nullArr; auto result = arr == nullArr; would have different semantics. The way that dynamic arrays are designed to work even if they're null mucks with this considerably here.
Do you not see they are different? You think arr == nullArr and arr == null are suppose to necessarily be the same semantics? That is patently false! You should rethink your position on that because it is wrong. null is a keyword in D and has a very special meaning and hence that meaning MUST be taken in to account. There is no harm in making them different. Your logic thinks that that they should be the same but if you are wrong then your whole argument is wrong. for example, Object o = null; then o == null should not be true even though "null == null" in some sense. == null is a test of validity. One never checks if null == null and it is a meaningless case so allowing it as a possibility is meaningless. You are treating null as if it is on the same level as objects and arrays and it is not. By doing so you lose the power of it being singled out as a keyword.
 You can't police programmers minds and get them to program 
 correctly.
That's true, but making things that are highly likely to be wrong illegal prevents bugs. e.g.
Not necessarily because you just create more bugs by doing that. Your son, the bubble boy, then does not develop an immune system that he should of developed by you trying to protect them from hurting himself. You should get out of the business of trying to prevent things that you don't even know are going to happen. It is a bad mindset to be in because, for all you know, those things will never happen. Time is better spent than trying to police everyone from doing anything wrong. 1. You can't do it. 2. You make things worse in the long run because who's policing you to keep you from screwing up? Do you know how many "bugs" are produced by people who are fixing "bugs"? We can surely bet more than zero.
 while(cond);

 is illegal in D precisely because it's error-prone. There are 
 cases where doing something like that would be perfectly 
 correct. e.g.

 while(++a != b);

 but you can do the exact same thing with empty parens

 while(++a != b) {}

 and all of those bugs with accidentally closing a loop with a 
 semicolon go away, and you don't lose any expressiveness. The 
 compiler just forces you to write it in a way that's far less 
 error-prone.
This is a different problem and therefor not applicable.
 Making it illegal to compare the null literal with == also 
 prevents bug, and you don't lose any expressiveness doing it 
 either. It's the same kind of logic. Making error-prone 
 constructs illegal when there's a simple equivalent that isn't 
 error-prone is good language design, because it prevents bugs 
 without actually restricting the programmer. It's when the 
 language starts disallowing things that aren't error-prone 
 and/or don't have simple equivalents that you start running 
 into problems with the compiler getting in your way and 
 treating you like a kid. For simple stuff like this, it 
 ultimately saves you time and effort without getting in your 
 way. At most, you occasionally have to replace foo == null with 
 foo is null or foo.length != 0, and it potentially saves you 
 hours of effort tracking down a subtle bug.

 - Jonathan M Davis
You certainly do lose expressiveness. You loose elegance because you cannot express logically related things in a logically related way. The problem is the WHOLE reason it is error prone is from who ever decided the dynamic array syntax of == null would not compare it the same way it does everything else. Basically someone thought they were going to be fancy and treat == null as the same as an allocated 0 length array. That was the problem from the get go. == null should have a very specific and consistent meaning and someone decided to change that in an irregular and inconsistent meaning and now we have less elegance in the language than we could. The reason why you are saying it is buggy is PRECISELY because of what was done wrong. Programmers assume that == null means the same thing it does everywhere else, but LO AND BEHOLD! Not in that one special case and if they don't know about that special case they hit the "bug". See, what you call bugs is really the programmers failing to know the special case that was created. The special case that really had no reason to be a special case. So, in fact, who ever decided on the rules here created more problems than they solved. Any time you create special cases you create complexity and that is what creates bugs of the type here. These bugs are entirely preventable with proper thought out consistency and these bugs are not the programmers fault but bugs in the design of the language, which are far worse. These are not the same types of bugs like a syntax error or a logic bug.
May 19 2018
parent IntegratedDimensions <IntegratedDimensions gmail.com> writes:
Furthermore:

https://issues.dlang.org/show_bug.cgi?id=3889

Shows real problems. You argue from the side that the bug already 
exists so we must work around it because we can't go back and 
"fix things". Who says? D has had breaking changes in the past so 
it is not a deal breaker. It is also a relatively easy transition 
because == null is very easy to find and fix.

With the mentality that one must always deal with introduced 
logic bugs that, if fixed, will break old code is insane. The 
whole point of fixing bugs is to make things work *correctly*.

The fact is someone decided it was a good idea to conflate null 
with some dynamic array BS and that is where all the problems 
come from. It should have never been done and this issue will 
persist until someone gets the balls to fix it.

After all, how do you know it won't actually make a lot of 
"buggy" code better?
May 19 2018