July 04, 2013
On Wed, 03 Jul 2013 19:15:19 +0100, Diggory <diggsey@googlemail.com> wrote:
> I would go as far as to say it should be impossible, or at least fairly difficult in safe code to distinguish (both intentionally and unintentionally) between an array of size zero with a non-null pointer and an array of size zero with a null pointer, and similar for associative arrays too.

Being able to represent both non-existent (null) and empty ([]) is a useful property, one that pointers and true references have.  If D can give us that power with arrays /and/ do it safely, then why wouldn't we want that?

If you don't care about the distinction between null and empty, you just check array.length == 0.

If you do care about the distinction you should be able to consistently tell them apart, and they should not mutate from one to the other as a side effect of other operations (as they currently do).

Statements like if "(array is null)"/"(array !is null)" should be used to check for a null (non-existent) array, and empty arrays should not match.

The main argument against having a distinction in the past has been that to have an empty array you need a non-null array pointer, which means you may have to allocate something which is a bit wasteful if you don't really care about the difference.

Tommi made a suggestion earlier in the thread that all empty arrays could point to the same global/thread local 1 byte block of pre-allocated memory, and this neatly solves the issue/complaint I believe.

R

-- 
Using Opera's revolutionary email client: http://www.opera.com/mail/
July 04, 2013
I am afraid I don't really follow here. How introducing new array literal (and making old one stronger typed) compromises typeof(null) features?

On Thursday, 4 July 2013 at 00:28:48 UTC, Andrei Alexandrescu wrote:
> typeof(null) has quite a few interesting properties. It's the closest type to the bottom of all types (we don't have an actual bottom type), and it subtypes many other types as mentioned.
>
> Introducing yet another type works against that nice uniformity and is yet another arbitrary little thing that people who learn the language would need to know about.
>
>
> Andrei

July 04, 2013
On Thu, 04 Jul 2013 05:25:30 -0400, Regan Heath <regan@netmail.co.nz> wrote:

> On Wed, 03 Jul 2013 19:10:40 +0100, bearophile <bearophileHUGS@lycos.com> wrote:
>> Telling apart the literal for an empty array from the literal of a empty but not null array is a bad idea that muds the language. And thankfully this currently fails:
>>
>> void main() {
>>      int[] emptyArray = [];
>>      assert(emptyArray !is null);
>> }
>
> As this comes up often you're probably aware that there are people (like myself) who find the distinction between a null (non-existant) array and an empty array useful.

Nobody questions that.  The biggest problem is making if(arr) mean if(arr.ptr) instead of if(arr.length)

What [] returns should not be an allocation.  And returning null is a reasonable implementation of that.

-Steve
July 04, 2013
On 07/04/2013 11:25 AM, Regan Heath wrote:
> ...
>
> Tommi's suggestion that all empty arrays share a common pointer is a
> good one and more or less solves the "it has to allocate memory" complaint.
> ...

(That was actually my suggestion. :o) )

Sharing a common pointer has some drawbacks as well, because it still makes [] somewhat special. It is probably worth it though.
July 04, 2013
On 07/04/2013 01:50 PM, Steven Schveighoffer wrote:
> On Thu, 04 Jul 2013 05:25:30 -0400, Regan Heath <regan@netmail.co.nz>
> wrote:
>
>> On Wed, 03 Jul 2013 19:10:40 +0100, bearophile
>> <bearophileHUGS@lycos.com> wrote:
>>> Telling apart the literal for an empty array from the literal of a
>>> empty but not null array is a bad idea that muds the language. And
>>> thankfully this currently fails:
>>>
>>> void main() {
>>>      int[] emptyArray = [];
>>>      assert(emptyArray !is null);
>>> }
>>
>> As this comes up often you're probably aware that there are people
>> (like myself) who find the distinction between a null (non-existant)
>> array and an empty array useful.
>
> Nobody questions that.  The biggest problem is making if(arr) mean
> if(arr.ptr) instead of if(arr.length)
>

if(arr.ptr) is what it means now.

> What [] returns should not be an allocation.  And returning null is a
> reasonable implementation of that.
>
> -Steve

static __gshared void[1] x;
return x[0..0];
July 04, 2013
On Thu, 04 Jul 2013 12:50:54 +0100, Steven Schveighoffer <schveiguy@yahoo.com> wrote:

> On Thu, 04 Jul 2013 05:25:30 -0400, Regan Heath <regan@netmail.co.nz> wrote:
>
>> On Wed, 03 Jul 2013 19:10:40 +0100, bearophile <bearophileHUGS@lycos.com> wrote:
>>> Telling apart the literal for an empty array from the literal of a empty but not null array is a bad idea that muds the language. And thankfully this currently fails:
>>>
>>> void main() {
>>>      int[] emptyArray = [];
>>>      assert(emptyArray !is null);
>>> }
>>
>> As this comes up often you're probably aware that there are people (like myself) who find the distinction between a null (non-existant) array and an empty array useful.
>
> Nobody questions that.
> The biggest problem is making if(arr) mean if(arr.ptr) instead of if(arr.length)

Indeed.  IMO if(arr) should mean if(arr.ptr) .. and I thought it did.. or did this change at some point?

> What [] returns should not be an allocation. And returning null is a reasonable implementation of that.

Whether there is an allocation or not is secondary.  The primary goal is for [] to represent empty, not null.  We have null, if we want to represent null we pass null.  What we lack is a way to represent empty.

So, I would say that what [] returns should be empty, and not null.

Secondarily we want to avoid allocation, so .. can we not have [] return a slice of length 0 with ptr set to a global pre-allocated single byte of memory?

R

-- 
Using Opera's revolutionary email client: http://www.opera.com/mail/
July 04, 2013
On Thursday, 4 July 2013 at 12:42:51 UTC, Timon Gehr wrote:
> On 07/04/2013 01:50 PM, Steven Schveighoffer wrote:
>> On Thu, 04 Jul 2013 05:25:30 -0400, Regan Heath <regan@netmail.co.nz>
>> wrote:
>>
>>> On Wed, 03 Jul 2013 19:10:40 +0100, bearophile
>>> <bearophileHUGS@lycos.com> wrote:
>>>> Telling apart the literal for an empty array from the literal of a
>>>> empty but not null array is a bad idea that muds the language. And
>>>> thankfully this currently fails:
>>>>
>>>> void main() {
>>>>     int[] emptyArray = [];
>>>>     assert(emptyArray !is null);
>>>> }
>>>
>>> As this comes up often you're probably aware that there are people
>>> (like myself) who find the distinction between a null (non-existant)
>>> array and an empty array useful.
>>
>> Nobody questions that.  The biggest problem is making if(arr) mean
>> if(arr.ptr) instead of if(arr.length)
>>
>
> if(arr.ptr) is what it means now.
>
>> What [] returns should not be an allocation.  And returning null is a
>> reasonable implementation of that.
>>
>> -Steve
>
> static __gshared void[1] x;
> return x[0..0];

+1. If you really want null, you can just as well use null for typeless, or "T[].init" for strong typing.

As stated before:
> Reasoning by extrapolation:
> int[] arr = [1, 2, 3]; // Array of 3 ints
> int[] arr = [1, 2]; // Array of 2 ints
> int[] arr = [1]; // Array of 1 ints
> int[] arr = []; // Array of 0 ints (not null)

As demonstrated this can be done with no allocations either.
July 04, 2013
On Thu, 04 Jul 2013 13:41:48 +0100, Timon Gehr <timon.gehr@gmx.ch> wrote:

> On 07/04/2013 11:25 AM, Regan Heath wrote:
>> ...
>>
>> Tommi's suggestion that all empty arrays share a common pointer is a
>> good one and more or less solves the "it has to allocate memory" complaint.
>> ...
>
> (That was actually my suggestion. :o) )

Whoops :P

> Sharing a common pointer has some drawbacks as well, because it still makes [] somewhat special. It is probably worth it though.

True, it may require some special casing in the array code on mutations of the array etc.

R

-- 
Using Opera's revolutionary email client: http://www.opera.com/mail/
July 04, 2013
On 07/04/13 14:41, Timon Gehr wrote:
> On 07/04/2013 11:25 AM, Regan Heath wrote:
>> ...
>>
>> Tommi's suggestion that all empty arrays share a common pointer is a
>> good one and more or less solves the "it has to allocate memory" complaint.
>> ...
> 
> (That was actually my suggestion. :o) )

What's the point?

[Mutation will cause reallocation; (void*)0 isn't special]

artur
July 04, 2013
On Thu, 04 Jul 2013 08:42:50 -0400, Timon Gehr <timon.gehr@gmx.ch> wrote:

> On 07/04/2013 01:50 PM, Steven Schveighoffer wrote:
>> On Thu, 04 Jul 2013 05:25:30 -0400, Regan Heath <regan@netmail.co.nz>
>> wrote:
>>
>>> On Wed, 03 Jul 2013 19:10:40 +0100, bearophile
>>> <bearophileHUGS@lycos.com> wrote:
>>>> Telling apart the literal for an empty array from the literal of a
>>>> empty but not null array is a bad idea that muds the language. And
>>>> thankfully this currently fails:
>>>>
>>>> void main() {
>>>>      int[] emptyArray = [];
>>>>      assert(emptyArray !is null);
>>>> }
>>>
>>> As this comes up often you're probably aware that there are people
>>> (like myself) who find the distinction between a null (non-existant)
>>> array and an empty array useful.
>>
>> Nobody questions that.  The biggest problem is making if(arr) mean
>> if(arr.ptr) instead of if(arr.length)
>>
>
> if(arr.ptr) is what it means now.

I know, and that is a problem.

-Steve

>> What [] returns should not be an allocation.  And returning null is a
>> reasonable implementation of that.
>
> static __gshared void[1] x;
> return x[0..0];

That's also a valid solution, along with:

void *x = null;
return x[0..0];

-Steve