digitalmars.D.learn - char[] == null
- Spacen Jasset (4/4) Nov 18 2015 Should this be allowed? What is it's purpose? It could compare
- rsw0x (4/9) Nov 18 2015 slices aren't arrays
- anonymous (4/6) Nov 18 2015 The language reference/specification [1] uses the term "dynamic array"
- Jonathan M Davis via Digitalmars-d-learn (25/31) Nov 19 2015 Exactly. T[] _is_ a dynamic array. Steven's otherwise wonderful article ...
- Spacen Jasset (9/19) Nov 19 2015 I mentioned this because it's bit of an error trap, that I fell
- Steven Schveighoffer (4/22) Nov 19 2015 Of course, if you are comparing something to an empty array, null is an
- Kagamin (3/8) Nov 19 2015 Actually char[] == null is a more usable one.
- Steven Schveighoffer (5/20) Nov 19 2015 It was not a mistake :) It's how I still think of it. The spec is
- Maxim Fomin (20/49) Nov 20 2015 Why formal definition of dynamic array caused confusion and is
- Chris Wright (22/27) Nov 18 2015 'null' is a value of ambiguous type. The compiler finds a set of
- Meta (23/27) Nov 18 2015 This is not true. Consider the following code:
- Chris Wright (18/45) Nov 18 2015 I tested the behavior and it matches what I said earlier:
- anonymous (2/3) Nov 18 2015 Yes, when it contains an element that's not equal to itself, e.g. NaN.
- Chris Wright (9/13) Nov 19 2015 Exactly.
- Jack Applegame (2/26) Nov 18 2015 Really? http://dpaste.dzfl.pl/b11346e8e341
- Meta (6/7) Nov 19 2015 Sorry, I said the exact opposite of what I meant to say. The
- Meta (2/10) Nov 19 2015 Actually, no it's not. Never mind.
- Kagamin (14/41) Nov 19 2015 Comparison is ok, weird behavior manifests in boolean context:
- BBaz (15/16) Nov 19 2015 IMHO no.
- Jack Applegame (3/3) Nov 19 2015 I prefer
Should this be allowed? What is it's purpose? It could compare two arrays, but surely not that each element of type char is null? char[] buffer; if (buffer == null) {}
Nov 18 2015
On Wednesday, 18 November 2015 at 20:57:08 UTC, Spacen Jasset wrote:Should this be allowed? What is it's purpose? It could compare two arrays, but surely not that each element of type char is null? char[] buffer; if (buffer == null) {}slices aren't arrays http://dlang.org/d-array-article.html
Nov 18 2015
On 18.11.2015 22:02, rsw0x wrote:slices aren't arrays http://dlang.org/d-array-article.htmlThe language reference/specification [1] uses the term "dynamic array" for T[] types. Let's not enforce a slang that's different from that. [1] http://dlang.org/arrays.html
Nov 18 2015
On Wednesday, November 18, 2015 22:15:19 anonymous via Digitalmars-d-learn wrote:On 18.11.2015 22:02, rsw0x wrote:Exactly. T[] _is_ a dynamic array. Steven's otherwise wonderful article on arrays in D ( http://dlang.org/d-array-article.html ) made the mistake of calling the buffer that T[] points to on the GC heap (assuming that even does point to the GC heap) the dynamic array. And per the language spec, that's not true at all. T[] is a dynamic array, whereas T[n] is a static array. The buffer referred to by T[] has no official name. And actually, the dynamic array really doesn't care whether it refers to a buffer on the GC heap, on that was malloced, a slice of a static array, etc. All of its operations are the same regardless, and all of the work. It's just that if the dynamic array does not refer to a buffer allocated on the GC heap for dynamic arrays, then it doesn't have any excess capacity for the dynamic array to grow into when you append to it, so appending to it forces the GC to reallocate its memory (as opposed to only having to reallocate sometimes when the buffer is already GC-allocated). And since the dynamic array itself does not manage its own memory, if you slice something other than GC-allocated memory to get a dynamic array, then it's up to you to make sure that you don't leak that memory or refer to it after it's been freed. However, every other aspect of T[] is identical regardless of what memory backs it, and most code really doesn't care what memory backs it. As far as the D language is concern, T[] _is_ a slice of memory, but it's also a dynamic array, whereas the memory that it's slicing is _not_ a dynamic array. - Jonathan M Davisslices aren't arrays http://dlang.org/d-array-article.htmlThe language reference/specification [1] uses the term "dynamic array" for T[] types. Let's not enforce a slang that's different from that. [1] http://dlang.org/arrays.html
Nov 19 2015
On Thursday, 19 November 2015 at 08:30:54 UTC, Jonathan M Davis wrote:On Wednesday, November 18, 2015 22:15:19 anonymous via Digitalmars-d-learn wrote:I mentioned this because it's bit of an error trap, that I fell into. char[] == null vs char[] is null Is there any good use for char[] == null ? If not, a warning might be helpful.[...]Exactly. T[] _is_ a dynamic array. Steven's otherwise wonderful article on arrays in D ( http://dlang.org/d-array-article.html ) made the mistake of calling the buffer that T[] points to on the GC heap (assuming that even does point to the GC heap) the dynamic array. And per the language spec, that's not true at all. [...]
Nov 19 2015
On 11/19/15 5:04 AM, Spacen Jasset wrote:On Thursday, 19 November 2015 at 08:30:54 UTC, Jonathan M Davis wrote:Of course, if you are comparing something to an empty array, null is an effective literal to create one. -SteveOn Wednesday, November 18, 2015 22:15:19 anonymous via Digitalmars-d-learn wrote:I mentioned this because it's bit of an error trap, that I fell into. char[] == null vs char[] is null Is there any good use for char[] == null ? If not, a warning might be helpful.[...]Exactly. T[] _is_ a dynamic array. Steven's otherwise wonderful article on arrays in D ( http://dlang.org/d-array-article.html ) made the mistake of calling the buffer that T[] points to on the GC heap (assuming that even does point to the GC heap) the dynamic array. And per the language spec, that's not true at all. [...]
Nov 19 2015
On Thursday, 19 November 2015 at 10:04:37 UTC, Spacen Jasset wrote:char[] == null vs char[] is null Is there any good use for char[] == null ? If not, a warning might be helpful.Actually char[] == null is a more usable one.
Nov 19 2015
On 11/19/15 3:30 AM, Jonathan M Davis via Digitalmars-d-learn wrote:On Wednesday, November 18, 2015 22:15:19 anonymous via Digitalmars-d-learn wrote:It was not a mistake :) It's how I still think of it. The spec is confusing, and my terminology, IMO, is a much more consistent (and accurate) way to think of it. -SteveOn 18.11.2015 22:02, rsw0x wrote:Exactly. T[] _is_ a dynamic array. Steven's otherwise wonderful article on arrays in D ( http://dlang.org/d-array-article.html ) made the mistake of calling the buffer that T[] points to on the GC heap (assuming that even does point to the GC heap) the dynamic array. And per the language spec, that's not true at all.slices aren't arrays http://dlang.org/d-array-article.htmlThe language reference/specification [1] uses the term "dynamic array" for T[] types. Let's not enforce a slang that's different from that. [1] http://dlang.org/arrays.html
Nov 19 2015
On Thursday, 19 November 2015 at 15:36:44 UTC, Steven Schveighoffer wrote:On 11/19/15 3:30 AM, Jonathan M Davis via Digitalmars-d-learn wrote:Why formal definition of dynamic array caused confusion and is inconsistent? It is well consistent with static array and other aggregate types notions. Consider this: int *x = new int; // this is 'int type' ans it is 'dynamic' int y; int *a = &y; // and this is not 'int type' The problem is treating chunk of heap memory as some kind of type (dynamic in this case). Type of object determines an interface of interacting with object while storage determines memory location and possibly duration of lifetime. It is possible to have object of any type to be allocated on different storages - for example, slice does not necessarily points to dynamic array (in your terms). C and C++ established a long tradition of such standard notions as object, lifetime, storage and type. From system language perspective calling memory a type (in other words, type of object depends on where it was allocated) does not make much sense.On Wednesday, November 18, 2015 22:15:19 anonymous via Digitalmars-d-learn wrote:It was not a mistake :) It's how I still think of it. The spec is confusing, and my terminology, IMO, is a much more consistent (and accurate) way to think of it. -SteveOn 18.11.2015 22:02, rsw0x wrote:Exactly. T[] _is_ a dynamic array. Steven's otherwise wonderful article on arrays in D ( http://dlang.org/d-array-article.html ) made the mistake of calling the buffer that T[] points to on the GC heap (assuming that even does point to the GC heap) the dynamic array. And per the language spec, that's not true at all.slices aren't arrays http://dlang.org/d-array-article.htmlThe language reference/specification [1] uses the term "dynamic array" for T[] types. Let's not enforce a slang that's different from that. [1] http://dlang.org/arrays.html
Nov 20 2015
On Wed, 18 Nov 2015 20:57:06 +0000, Spacen Jasset wrote:Should this be allowed? What is it's purpose? It could compare two arrays, but surely not that each element of type char is null? char[] buffer; if (buffer == null) {}'null' is a value of ambiguous type. The compiler finds a set of compatible types for them by applying known implicit conversions. 'null' can implicitly convert to 'char[]'. Arrays, of course, are tuples consisting of a start pointer and length. A null array is essentially {ptr = null, length = 0}. Array equality is implemented as, roughly: --- if (a.length != b.length) return false; foreach (i, v; a) { if (v != b[i]) return false; } return true; --- (That's not quite how it's implemented; it uses runtime functions and indirection. But it's the same algorithm.) This shows us that all 0-length arrays are equal. Pretty much as we'd expect. So your code is equivalent to: --- char[] buffer; if (buffer.length == 0) {} ---
Nov 18 2015
On Wednesday, 18 November 2015 at 23:53:01 UTC, Chris Wright wrote:--- char[] buffer; if (buffer.length == 0) {} ---This is not true. Consider the following code: import std.stdio; void main() { int[] a = [0, 1, 2]; //4002E000 3 writeln(a.ptr, " ", a.length); //Is not triggered, obviously assert(a == null); a.length = 0; //4002E000 0 writeln(a.ptr, " ", a.length, " ", a); //Is not triggered, not as obvious assert(a == null); } There are cases when an array may have 0 length but a non-null pointer. If you want to check if an array's length is 0, you must explicitly check its length member. Checking if an array is equal to null only compares its pointer field to null. It does *not* check the length.
Nov 18 2015
On Thu, 19 Nov 2015 03:53:46 +0000, Meta wrote:On Wednesday, 18 November 2015 at 23:53:01 UTC, Chris Wright wrote:I tested the behavior and it matches what I said earlier: --- auto c = "hello world".dup; auto b = c[0..0]; writeln(b == null); // prints true writeln(b.ptr == null); // prints false --- This is because array comparison is a memberwise comparison and not a reference comparison, as you can see more clearly with: --- enum int[] a = [1, 2, 3]; writeln(a == a.dup); // prints true --- Or you can check the runtime's implementation of array equality at https://github.com/D-Programming-Language/druntime/blob/master/src/ object.d#L437 . Just for fun, is an array ever not equal to itself?--- char[] buffer; if (buffer.length == 0) {} ---This is not true. Consider the following code: import std.stdio; void main() { int[] a = [0, 1, 2]; //4002E000 3 writeln(a.ptr, " ", a.length); //Is not triggered, obviously assert(a == null); a.length = 0; //4002E000 0 writeln(a.ptr, " ", a.length, " ", a); //Is not triggered, not as obvious assert(a == null); } There are cases when an array may have 0 length but a non-null pointer. If you want to check if an array's length is 0, you must explicitly check its length member. Checking if an array is equal to null only compares its pointer field to null. It does *not* check the length.
Nov 18 2015
On 19.11.2015 06:18, Chris Wright wrote:Just for fun, is an array ever not equal to itself?Yes, when it contains an element that's not equal to itself, e.g. NaN.
Nov 18 2015
On Thu, 19 Nov 2015 07:28:28 +0100, anonymous wrote:On 19.11.2015 06:18, Chris Wright wrote:Exactly. If NaN-like cases didn't exist, TypeInfo_Array could have an optimization: if the pointers and lengths of its inputs were both equal, the arrays are equal. But adding this optimization would result in problematic behavior. Specifically: auto a = [float.nan]; assert(a == a); // passes under proposed optimization, fails now assert(a == a.dup); // fails under proposed optimization, fails nowJust for fun, is an array ever not equal to itself?Yes, when it contains an element that's not equal to itself, e.g. NaN.
Nov 19 2015
On Thursday, 19 November 2015 at 03:53:48 UTC, Meta wrote:On Wednesday, 18 November 2015 at 23:53:01 UTC, Chris Wright wrote:Really? http://dpaste.dzfl.pl/b11346e8e341[...]This is not true. Consider the following code: import std.stdio; void main() { int[] a = [0, 1, 2]; //4002E000 3 writeln(a.ptr, " ", a.length); //Is not triggered, obviously assert(a == null); a.length = 0; //4002E000 0 writeln(a.ptr, " ", a.length, " ", a); //Is not triggered, not as obvious assert(a == null); } There are cases when an array may have 0 length but a non-null pointer. If you want to check if an array's length is 0, you must explicitly check its length member. Checking if an array is equal to null only compares its pointer field to null. It does *not* check the length.
Nov 18 2015
On Thursday, 19 November 2015 at 06:57:20 UTC, Jack Applegame wrote:Really? http://dpaste.dzfl.pl/b11346e8e341Sorry, I said the exact opposite of what I meant to say. The `assert(a == null)` *is* triggered because the expression `a == null` fails, even though a.length == 0. You should not use `a == null` to check if an array is empty. Always use a.length == 0.
Nov 19 2015
On Thursday, 19 November 2015 at 13:49:18 UTC, Meta wrote:On Thursday, 19 November 2015 at 06:57:20 UTC, Jack Applegame wrote:Actually, no it's not. Never mind.Really? http://dpaste.dzfl.pl/b11346e8e341Sorry, I said the exact opposite of what I meant to say. The `assert(a == null)` *is* triggered because the expression `a == null` fails, even though a.length == 0. You should not use `a == null` to check if an array is empty. Always use a.length == 0.
Nov 19 2015
On Thursday, 19 November 2015 at 03:53:48 UTC, Meta wrote:On Wednesday, 18 November 2015 at 23:53:01 UTC, Chris Wright wrote:Comparison is ok, weird behavior manifests in boolean context: void main() { int[] a = [0, 1, 2]; //4002E000 3 assert(a != null); assert(!!a); //passes, ok a.length = 0; //4002E000 0 assert(a == null); assert(!!a); //still passes! }--- char[] buffer; if (buffer.length == 0) {} ---This is not true. Consider the following code: import std.stdio; void main() { int[] a = [0, 1, 2]; //4002E000 3 writeln(a.ptr, " ", a.length); //Is not triggered, obviously assert(a == null); a.length = 0; //4002E000 0 writeln(a.ptr, " ", a.length, " ", a); //Is not triggered, not as obvious assert(a == null); } There are cases when an array may have 0 length but a non-null pointer. If you want to check if an array's length is 0, you must explicitly check its length member. Checking if an array is equal to null only compares its pointer field to null. It does *not* check the length.
Nov 19 2015
On Wednesday, 18 November 2015 at 20:57:08 UTC, Spacen Jasset wrote:Should this be allowed ?IMHO no. It's better to use `.length` to test if an array is empty. Why ? Because the day you'll have a function whose parameter is a pointer to an array, comparing to null will become completly confusing: --- void whyPeopleShouldUseLength(char[]* buffptr) { if (buffptr != null && buffptr.length > 0) {} } --- Here you really have to test if the variable is assigned, it's not a shortcut to test the internal buffptr `.ptr` member.
Nov 19 2015
I prefer import std.array; if(!arr.empty) {}
Nov 19 2015