July 05, 2013
On 7/5/13 2:05 AM, Regan Heath wrote:
> On Thu, 04 Jul 2013 18:26:09 +0100, Andrei Alexandrescu
> <SeeWebsiteForEmail@erdani.org> wrote:
>> Why do you want so much an empty array that's not null? I can't make
>> sense of this entire argument.
>
> Suppose you have a web page, suppose it has a text field on it called
> "comment". Suppose you load a pre-existing record from your database and
> populate the page, suppose it had a value for comment, suppose you want
> to set that comment to be blank. you edit and click save.
>
> The code backing this page is going to get a string for "comment", that
> string should be empty but not null.
>
> Why? Because if it were null it would have a different meaning. It would
> mean that the comment field was not present on the page at all, and
> should not be altered.

I find the example tenuous. Even assuming it has merit, it does not explain the need for a syntactic _literal_ to fulfill that need.

> There are many such examples.

I am not convinced there are many such examples. I'd call it poor design to make it a cornerstone to distinguish between empty arrays that are null and empty arrays that are not only non-null, but aren't part of any other array!

Let me emphasize the last part. Ironically, there is a potential interesting use of empty non-null arrays as anchors: an empty slice referring to the interior of an array may be combined with another slice, pointer, or length, to create a new, meaningful slice. However, the discussed literal does nothing of that kind - it just fabricates a slice of an array that does not exist.

> All of them can be worked around by
> various means but these are all more complex and require additional
> containers or variables to represent state.

I would say those are better designs.

> null - does not exist, was not specified.
> empty - exists and was intentionally set to be empty.

Such empty arrays occur as natural reductions from other arrays. Why yet another literal for such?

> I think arrays will be most useful if we can treat them like safe
> reference types - this wrappers around the unsafe ptr reference type. To
> do that, we need null/empty to be stable/reliable states.
>
> If not, then array becomes like 'int' and we have to invent a special
> value to represent the null case (or use other containers/variables to
> represent null) like we do for int.

I am not convinced.


Andrei
July 05, 2013
On Friday, 5 July 2013 at 16:22:12 UTC, Andrei Alexandrescu wrote:
> On 7/5/13 2:05 AM, Regan Heath wrote:
>> Why? Because if it were null it would have a different meaning. It would
>> mean that the comment field was not present on the page at all, and
>> should not be altered.
>
> I find the example tenuous. Even assuming it has merit, it does not explain the need for a syntactic _literal_ to fulfill that need.

TBH my main concern is the stability of the null/empty states of arrays, not the literal.  But, I think the current means by which you can create empty arrays, without slicing them from an existing array or variable is hackish at best.

Imagine we have a function which accepts an optional array.  Passing null means, not specified/do nothing, passing non-null means assign/use the value.

If we have an existing array or even a local variable of the right type we can slice off it to pass empty, but otherwise we're screwed .. right?

i.e. How can you call 'foo' below from 'bar' passing an empty array for a, b, or c in a generic manner?

import std.stdio;

void foo(T,U,V)(T[] a, U[] b, V[] c)
{
  writefln("a !is null = %s", (a !is null));
  writefln("a.length is = %s", a.length);
  writefln("b !is null = %s", (b !is null));
  writefln("b.length is = %s", b.length);
  writefln("c !is null = %s", (c !is null));
  writefln("c.length is = %s", c.length);
}

void bar(T,U,V)()
{
  V[] c1 = null;
  V[] c2 = new V[0];

  foo!(T,U,V)([], // null, length = 0
    null,         // null, length = 0
    c1);          // null, length = 0
	
  writefln("");

  U i;

  foo!(T,U,V)(cast(T[])"", // !null, length = 0
    cast(U[])(&i)[0..0],   // !null, length = 0
    c2);                   // *null* length = 5
}

void main()
{
  bar!(dchar,int,bool)();
}

The dchar[] works because I cheated/knew the type, the int[] requires a local variable to slice off, the bool[] is a local array which in the 2nd case is still null!

Is there a better way to do it?

>> There are many such examples.
>
> I am not convinced there are many such examples. I'd call it poor design to make it a cornerstone to distinguish between empty arrays that are null and empty arrays that are not only non-null, but aren't part of any other array!

To be clear I want to be able to distinguish between not-specified and specified.  In the specified case I can tell empty/not empty by using length.

This may seem like splitting hairs but from my point of view there is no such thing as "empty arrays that are null".  If the array/slice/parameter "is null" then it is not-specified, or non-existent, not empty.  For example if you start with a set of 2 items, take 2 items away and you have an empty set, take the set itself away and you have no set at all (non-existent/not-specified).

> Let me emphasize the last part. Ironically, there is a potential interesting use of empty non-null arrays as anchors: an empty slice referring to the interior of an array may be combined with another slice, pointer, or length, to create a new, meaningful slice. However, the discussed literal does nothing of that kind - it just fabricates a slice of an array that does not exist.

Thus allowing us to pass a set which exists but contains no items.

>> All of them can be worked around by
>> various means but these are all more complex and require additional
>> containers or variables to represent state.
>
> I would say those are better designs.

How exactly?  They're all more complex and/or indirect.  Having a single variable which can reflect the intent directly and without relying on external state is surely "better".

>> null - does not exist, was not specified.
>> empty - exists and was intentionally set to be empty.
>
> Such empty arrays occur as natural reductions from other arrays. Why yet another literal for such?

Yet another literal?  What other literal are we talking about?  What if you don't have another array or variable to slice off?

>> I think arrays will be most useful if we can treat them like safe
>> reference types - this wrappers around the unsafe ptr reference type. To
>> do that, we need null/empty to be stable/reliable states.
>>
>> If not, then array becomes like 'int' and we have to invent a special
>> value to represent the null case (or use other containers/variables to
>> represent null) like we do for int.
>
> I am not convinced.

Fair enough.

It just seems .. annoying to me that I cannot do with a char[] array what I can do with a char* pointer (represent non-specified, empty, not empty).  That, plus the fact that the D array/slice behaviour is not reliable, or consistent, makes it seem like a rough edge.
July 08, 2013
deadalnix:

> [] and [:] aren't even remotely close to be strongly typed.

It's a matter of degrees of how much "strongly" typed things are. The current situation is significantly more weakly typed than what I have proposed. It doesn't even tell apart a light reference from a fat pointer.

Bye,
bearophile
1 2 3 4 5 6 7 8 9
Next ›   Last »