First part:

I prefer a language that uses literals that are as much as possible clear, 
readable and unambiguous. In D "null" can represent empty pointers, empty class 
references, and empty dynamic arrays:


int[] foo(int[] a) {
    return null;
}
int[] foo2(int[] a) {
    return [];
}
void main() {
    foo(cast(int[])null);
    foo(null);
    foo([]);
    foo2(cast(int[])null);
    foo2(null);
    foo2([]);
}


But "null" is not a clear way to represent an empty array, that is a struct of 
two items (this reminds me of the untidy usage of 0 to represent a null pointer 
in C). So I propose to remove/deprecate the usage of "null" to represent an 
empty dynamic array (the Delight D-derived language already allows only [] for 
such purpose).


Note: [] is not fully unambiguous, it doesn't specify a type. Specifying a type 
can be useful, because you can use it to give as argument to a template 
function an array of the correct type:


import std.stdio: writeln;
void foo(T)(T[] a) {
    writeln(typeid(T));
}
void main() {
    // OK, int[]
    foo(cast(int[])null);

    // OK, int[]
    foo(cast(int[])[]);

    // Partially OK, inside foo 'a' is of type void[]
    foo([]);

    // Bad, Error: template test.foo(T) does not match any function template 
declaration
    foo(null);
}


In such situations cast(int[])[] is enough. I think this idiom isn't common in 
D code.

------------------------------------------

Second part (this is less nice than the first part):

In D null can also be used to represent an empty associative array. If you 
think of AAs as instances of a class to be used by reference, then using a null 
to represent an empty AA is meaningful (the main difference is that you don't 
need "new" to allocate it at the beginning).

But I think currently associative arrays are not instances of a normal class, 
so this is a fourth different overload of the meaning of "null". To remove some 
semantic overload, the empty untyped associative array can be represented with 
a different literal, for example like:

[:]

Where needed, for templates, you can use that literal with types too, as in the 
dynamic array case:

cast(int[float])[:]

If in future associative arrays will become true instances of a templated 
class, then it's better to restore the usage of 'null'.


If you think there is something good in what I have written, then later I am 
willing to create a bug report from the first part (or both parts) of this post.

Bye,
bearophile

Reply via email to