Thread overview
Distinguish between a null array and an empty array
May 24, 2020
bauss
May 24, 2020
bauss
May 24, 2020
ag0aep6g
May 24, 2020
bauss
May 24, 2020
ag0aep6g
May 26, 2020
WebFreak001
May 27, 2020
Dukc
May 24, 2020
Jonathan M Davis
May 26, 2020
Nathan S.
May 24, 2020
Is there a way to do that?

Since the following are both true:

int[] a = null;
int[] b = [];

assert(a is null);
assert(!a.length);

assert(b is null);
assert(!b.length);

What I would like is to tell that b is an empty array and a is a null array.
May 24, 2020
On Sunday, 24 May 2020 at 12:12:31 UTC, bauss wrote:
> Is there a way to do that?
>
> Since the following are both true:
>
> int[] a = null;
> int[] b = [];
>
> assert(a is null);
> assert(!a.length);
>
> assert(b is null);
> assert(!b.length);
>
> What I would like is to tell that b is an empty array and a is a null array.

I'm aware that D is special in that they're equal here BUT in my use-case I must absolutely handle them differently.
May 24, 2020
On 24.05.20 14:12, bauss wrote:
> Is there a way to do that?
> 
> Since the following are both true:
> 
> int[] a = null;
> int[] b = [];
> 
> assert(a is null);
> assert(!a.length);
> 
> assert(b is null);
> assert(!b.length);
> 
> What I would like is to tell that b is an empty array and a is a null array.

No way. `null` and `[]` are the same thing for arrays. (Ulike `""` for strings which has a non-null `.ptr`.)

You can distinguish `null` from other (non-null, non-`[]`) empty arrays. For example:

----
int[] b = [1, 2, 3];
b = b[0 .. 0];

assert(b !is null);
assert(!b.length);
----
May 24, 2020
On Sunday, May 24, 2020 6:12:31 AM MDT bauss via Digitalmars-d-learn wrote:
> Is there a way to do that?
>
> Since the following are both true:
>
> int[] a = null;
> int[] b = [];
>
> assert(a is null);
> assert(!a.length);
>
> assert(b is null);
> assert(!b.length);
>
> What I would like is to tell that b is an empty array and a is a null array.

There really is no difference between null and []. The compiler will use the exact same value for both, since it makes no sense to allocate anything for an empty array. If you want an array that's empty but non-null, then you'll have to create a non-empty array and then slice it or set its length to 0 so that it actually has a value for its ptr property other than null.

Regardless, == will never differentiate between a null and empty array, because it's going to compare the lengths of the arrays and then compare the individual elements if the lengths are the same. And with a length of 0, there's no reason to ever check the elements, so the ptr value is irrelevant. If you want to check whether an array is actually null, then you need to use the is operator or check the ptr property explicitly.

And of course, the normal warnings apply that trying to differentiate between null and empty arrays in D is almost certainly something that you shouldn't be doing. You can do it if you're _very_ careful, but it's almost always a terrible idea. As dumb as it arguably is, wrapping the array in a Nullable would be _far_ less error-prone if you need to differentiate between an array that's empty and not having a value.

- Jonathan M Davis



May 24, 2020
On Sunday, 24 May 2020 at 12:26:42 UTC, ag0aep6g wrote:
> On 24.05.20 14:12, bauss wrote:
>> Is there a way to do that?
>> 
>> Since the following are both true:
>> 
>> int[] a = null;
>> int[] b = [];
>> 
>> assert(a is null);
>> assert(!a.length);
>> 
>> assert(b is null);
>> assert(!b.length);
>> 
>> What I would like is to tell that b is an empty array and a is a null array.
>
> No way. `null` and `[]` are the same thing for arrays. (Ulike `""` for strings which has a non-null `.ptr`.)
>
> You can distinguish `null` from other (non-null, non-`[]`) empty arrays. For example:
>
> ----
> int[] b = [1, 2, 3];
> b = b[0 .. 0];
>
> assert(b !is null);
> assert(!b.length);
> ----

Dang, that sucks there is no proper way and I would say that's a big flaw of D.

Because what I need it for is for some data serialization but if the value is an empty array then it should be present and if it's null then it should not be present.

Since null is used to say "ignore this" in the data serialization.

Oh well.
May 24, 2020
On 24.05.20 14:29, bauss wrote:
> Dang, that sucks there is no proper way and I would say that's a big flaw of D.
> 
> Because what I need it for is for some data serialization but if the value is an empty array then it should be present and if it's null then it should not be present.
> 
> Since null is used to say "ignore this" in the data serialization.

You can use std.typecons.Nullable (or a similar wrapper) to add an extra "ignore this" value to a type.
May 26, 2020
On Sunday, 24 May 2020 at 12:12:31 UTC, bauss wrote:
> Is there a way to do that?
>
> Since the following are both true:
>
> int[] a = null;
> int[] b = [];
>
> assert(a is null);
> assert(!a.length);
>
> assert(b is null);
> assert(!b.length);
>
> What I would like is to tell that b is an empty array and a is a null array.

Yes you can tell: your `is null` check actually works, the part that doesn't work is that `int[] b = []` is initializing b to null.

Here's an example:

---
    int[0] emptyArray;
    int[] a = null; // a.ptr is null, a.length is 0
    int[] b = emptyArray[]; // b.ptr is non-null, b.length is 0

    assert(a is null);
    assert(!a.length);

    assert(b !is null);
    assert(!b.length);
---

May 26, 2020
On Sunday, 24 May 2020 at 12:37:20 UTC, ag0aep6g wrote:
> On 24.05.20 14:29, bauss wrote:
>> Dang, that sucks there is no proper way and I would say that's a big flaw of D.
>> 
>> Because what I need it for is for some data serialization but if the value is an empty array then it should be present and if it's null then it should not be present.
>> 
>> Since null is used to say "ignore this" in the data serialization.
>
> You can use std.typecons.Nullable (or a similar wrapper) to add an extra "ignore this" value to a type.

and just in case you use vibe.d serialization (JSON, BSON or other custom ones), there is a new @embedNullable UDA which treats Nullable!T inside a map as a T or completely omits it if it's null ;)
May 26, 2020
On 5/24/20 8:12 AM, bauss wrote:
> Is there a way to do that?
> 
> Since the following are both true:
> 
> int[] a = null;
> int[] b = [];
> 
> assert(a is null);
> assert(!a.length);
> 
> assert(b is null);
> assert(!b.length);
> 
> What I would like is to tell that b is an empty array and a is a null array.

The issue is simply that [] is the same as null.

Try this:

T[] emptyArr(T)() @trusted
{
   T* p = null;
   return p[1 .. 1];
}


int[] b = emptyArr!int;

assert(b !is null);
assert(!b.length);

-Steve
May 27, 2020
On Sunday, 24 May 2020 at 12:29:23 UTC, bauss wrote:
> Dang, that sucks there is no proper way and I would say that's a big flaw of D.
>
> Because what I need it for is for some data serialization but if the value is an empty array then it should be present and if it's null then it should not be present.
>
> Since null is used to say "ignore this" in the data serialization.
>
> Oh well.

If you want to avoid the memory cost of `Nullable`, I think you could still have a special value for "no data". But I wouldn't use D `null` for it, because it's so common for it to be used for empty values. Instead, I'd define a small data section somewhere. You test whether the array points to it (`&arr[0] == &nullSection[0]`), and if, it means no data.