May 16, 2012
On Wed, 16 May 2012 13:52:57 -0400, H. S. Teoh <hsteoh@quickfur.ath.cx> wrote:

> On Wed, May 16, 2012 at 01:36:27PM -0400, Steven Schveighoffer wrote:
>> On Wed, 16 May 2012 13:16:36 -0400, H. S. Teoh
>> <hsteoh@quickfur.ath.cx> wrote:
>>
>> >On Wed, May 16, 2012 at 01:07:54PM -0400, Steven Schveighoffer wrote:
>> >[...]
>> >>For example:
>> >>
>> >>auto str = "abcabc";
>> >>assert(str[0..3] == str[3..$]); // pass
>> >>assert(str[0..3] is str[3..$]); // fail
>> >>
>> >>which is very counterintuitive.
>> >[...]
>> >
>> >I don't find that counterintuitive at all. To me, 'is' concerns
>> >memory identity: are the two things actually one and the same _in
>> >memory_? (In this case, no, because they are different chunks of
>> >memory that just happens to contain the same values.) Whereas '=='
>> >concerns logical identity: do the two things represent the same
>> >logical entity? (In this case, yes, these two arrays contain exactly
>> >the same elements.)
>> >
>> >I'd argue that 99% of the time, what you want is logical identity
>> >(i.e., ==), not memory identity.
>>
>> What's counter intuitive is if you use null as a 'special marker',
>> then you use == in most cases, but that one case where you want to
>> 'check for the special marker', in which case you *have* to use is.
> [...]
>
> It depends upon one's mental model of what an array is.
>
> If you think of an array as a container that exists apart from its
> contents, then you'd expect null != [] because null means even the
> container itself doesn't exist, whereas [] means the container exists
> but contains nothing.
>
> However, if you regard the array simply as the sum total of its
> contents, then you'd expect null == [] because there is no container to
> speak of, either there are elements, or there are none. When there are
> no elements, there is also no array (or equivalently, the array is
> empty). Therefore, null and [] are the same thing.
>
> It seems that D takes the latter view, at least as far as == is
> concerned. Thus, to distinguish between null and [], one has to bypass
> == and use 'is' (i.e., open up the hood of the mental model of an array,
> and look into its actual implementation).

Part of the source of this confusion is that D slices are not actually arrays or containers.  They reference, they don't contain.

-Steve
May 16, 2012
On Wed, May 16, 2012 at 02:03:44PM -0400, Steven Schveighoffer wrote:
> On Wed, 16 May 2012 13:52:57 -0400, H. S. Teoh <hsteoh@quickfur.ath.cx> wrote:
[...]
> >It depends upon one's mental model of what an array is.
> >
> >If you think of an array as a container that exists apart from its contents, then you'd expect null != [] because null means even the container itself doesn't exist, whereas [] means the container exists but contains nothing.
> >
> >However, if you regard the array simply as the sum total of its contents, then you'd expect null == [] because there is no container to speak of, either there are elements, or there are none. When there are no elements, there is also no array (or equivalently, the array is empty). Therefore, null and [] are the same thing.
> >
> >It seems that D takes the latter view, at least as far as == is concerned. Thus, to distinguish between null and [], one has to bypass == and use 'is' (i.e., open up the hood of the mental model of an array, and look into its actual implementation).
> 
> Part of the source of this confusion is that D slices are not actually arrays or containers.  They reference, they don't contain.
[...]

Right, which is why D's arrays (or rather, slices) are closer to the second model than the first. Actually, arrays only exist in the GC, right? Even an "explicitly declared" array is really just a slice, that just happens to reference the contents of that chunk of GC memory.

Except static arrays, of course, but we're not worried about those here.


T

-- 
Never trust an operating system you don't have source for! -- Martin Schulze
May 16, 2012
On Wed, 16 May 2012 14:32:44 -0400, H. S. Teoh <hsteoh@quickfur.ath.cx> wrote:

> Right, which is why D's arrays (or rather, slices) are closer to the
> second model than the first. Actually, arrays only exist in the GC,
> right? Even an "explicitly declared" array is really just a slice, that
> just happens to reference the contents of that chunk of GC memory.

Yes.

-Steve
May 16, 2012
Le 16/05/2012 12:10, Timon Gehr a écrit :
> On 05/16/2012 12:29 AM, deadalnix wrote:
>> Le 15/05/2012 20:34, Alex Rønne Petersen a écrit :
>>> Besides, this is probably not going to change anyway. We're focusing on
>>> stabilizing the language, not changing it.
>>>
>>
>> This always have been a design mistake to auto cast array in pointers.
>> This is silent fallback to usafe world, and what we want to avoid.
>>
>
> Getting a pointer to the beginning of a zero-terminated string literal
> is perfectly safe.
>
>> This has no benefit because using .ptr isn't really complex and make the
>> transition obvious.
>>
>> This has been raised many time in the past as being an issue, and it fit
>> nicely here.
>>
>
> This is a compile time error:
>
> int[] arr;
> int* p=arr;
>
> What exactly are you asking for?
>

void foo(const(char)*);

foo("bar");

isn't .

>> Having \0 terminated string in D were it has no usage is quite dumb.
>
> What you don't seem to get is that it actually has usage.

I understand that. I want to propose something more subtle.

Array in D are already typed according to what the are assigned. int[] foo = [1, 2] and immutable(int)[] = [1, 2] are both possible). Isn't it possible to \0 terminate string chen they are used as char* and not when they are used as array ?
May 16, 2012
On 16-05-2012 22:00, deadalnix wrote:
> Le 16/05/2012 12:10, Timon Gehr a écrit :
>> On 05/16/2012 12:29 AM, deadalnix wrote:
>>> Le 15/05/2012 20:34, Alex Rønne Petersen a écrit :
>>>> Besides, this is probably not going to change anyway. We're focusing on
>>>> stabilizing the language, not changing it.
>>>>
>>>
>>> This always have been a design mistake to auto cast array in pointers.
>>> This is silent fallback to usafe world, and what we want to avoid.
>>>
>>
>> Getting a pointer to the beginning of a zero-terminated string literal
>> is perfectly safe.
>>
>>> This has no benefit because using .ptr isn't really complex and make the
>>> transition obvious.
>>>
>>> This has been raised many time in the past as being an issue, and it fit
>>> nicely here.
>>>
>>
>> This is a compile time error:
>>
>> int[] arr;
>> int* p=arr;
>>
>> What exactly are you asking for?
>>
>
> void foo(const(char)*);
>
> foo("bar");
>
> isn't .

And shouldn't be. Working with C APIs or just working on druntime would be a nightmare.

>
>>> Having \0 terminated string in D were it has no usage is quite dumb.
>>
>> What you don't seem to get is that it actually has usage.
>
> I understand that. I want to propose something more subtle.
>
> Array in D are already typed according to what the are assigned. int[]
> foo = [1, 2] and immutable(int)[] = [1, 2] are both possible). Isn't it
> possible to \0 terminate string chen they are used as char* and not when
> they are used as array ?

Theoretically, yes, practically, not really.

void myLog(string msg)
{
    printf(msg);
}

-- 
Alex Rønne Petersen
alex@lycus.org
http://lycus.org
May 16, 2012
On Wed, 16 May 2012 16:19:36 -0400, Alex Rønne Petersen <alex@lycus.org> wrote:

> Theoretically, yes, practically, not really.
>
> void myLog(string msg)
> {
>      printf(msg);
> }

Wait, this should be an error.  You need toStringz there.

-Steve
May 16, 2012
Le 16/05/2012 22:19, Alex Rønne Petersen a écrit :
> On 16-05-2012 22:00, deadalnix wrote:
>> Le 16/05/2012 12:10, Timon Gehr a écrit :
>>> On 05/16/2012 12:29 AM, deadalnix wrote:
>>>> Le 15/05/2012 20:34, Alex Rønne Petersen a écrit :
>>>>> Besides, this is probably not going to change anyway. We're
>>>>> focusing on
>>>>> stabilizing the language, not changing it.
>>>>>
>>>>
>>>> This always have been a design mistake to auto cast array in pointers.
>>>> This is silent fallback to usafe world, and what we want to avoid.
>>>>
>>>
>>> Getting a pointer to the beginning of a zero-terminated string literal
>>> is perfectly safe.
>>>
>>>> This has no benefit because using .ptr isn't really complex and make
>>>> the
>>>> transition obvious.
>>>>
>>>> This has been raised many time in the past as being an issue, and it
>>>> fit
>>>> nicely here.
>>>>
>>>
>>> This is a compile time error:
>>>
>>> int[] arr;
>>> int* p=arr;
>>>
>>> What exactly are you asking for?
>>>
>>
>> void foo(const(char)*);
>>
>> foo("bar");
>>
>> isn't .
>
> And shouldn't be. Working with C APIs or just working on druntime would
> be a nightmare.
>
>>
>>>> Having \0 terminated string in D were it has no usage is quite dumb.
>>>
>>> What you don't seem to get is that it actually has usage.
>>
>> I understand that. I want to propose something more subtle.
>>
>> Array in D are already typed according to what the are assigned. int[]
>> foo = [1, 2] and immutable(int)[] = [1, 2] are both possible). Isn't it
>> possible to \0 terminate string chen they are used as char* and not when
>> they are used as array ?
>
> Theoretically, yes, practically, not really.
>
> void myLog(string msg)
> {
> printf(msg);
> }
>

This is exactly why array shouldn't fallback into pointer silently.

Your code here is flawed and unsafe. You NEED a toStringz here.
May 16, 2012
Le 16/05/2012 15:12, Steven Schveighoffer a écrit :
> On Tue, 15 May 2012 04:42:10 -0400, deadalnix <deadalnix@gmail.com> wrote:
>
>> Le 14/05/2012 21:53, Steven Schveighoffer a écrit :
>>> On Mon, 14 May 2012 15:30:25 -0400, deadalnix <deadalnix@gmail.com>
>>> wrote:
>>>
>>>> Le 14/05/2012 16:37, Steven Schveighoffer a écrit :
>>>>> Note that [] is a request to the runtime to build an empty array. The
>>>>> runtime detects this, and rather than consuming a heap allocation to
>>>>> build nothing, it simply returns a null-pointed array. This is 100%
>>>>> the
>>>>> right decision, and I don't think anyone would ever convince me (or
>>>>> Andrei or Walter) otherwise.
>>>>>
>>>>
>>>> Obviously this is the right thing to do !
>>>>
>>>> The question is why an array of length 0 isn't nulled ? It lead to
>>>> confusing semantic here, and can keep alive memory that can't be
>>>> accessed.
>>>
>>> int[] arr;
>>> arr.reserve(10000);
>>> assert(arr.length == 0);
>>>
>>> -Steve
>>
>> The length isn't set to 0 here. You obviously don't want that to be
>> nulled.
>
> The assert disagrees with you :)
>
> -Steve

The length IS 0. It IS 0 before the call to reserve. It is never SET to 0.
May 16, 2012
On 16-05-2012 22:42, Steven Schveighoffer wrote:
> On Wed, 16 May 2012 16:19:36 -0400, Alex Rønne Petersen <alex@lycus.org>
> wrote:
>
>> Theoretically, yes, practically, not really.
>>
>> void myLog(string msg)
>> {
>> printf(msg);
>> }
>
> Wait, this should be an error. You need toStringz there.
>
> -Steve

Sorry, I meant:

void myLog(string msg)
{
    printf(msg.ptr);
}

(Which works as expected because string literals are null-terminated. This is also how things work when you pass a string literal to a const(char)* value; it just does "literal".ptr.)

-- 
Alex Rønne Petersen
alex@lycus.org
http://lycus.org
May 16, 2012
On Wed, 16 May 2012 17:06:41 -0400, Alex Rønne Petersen <alex@lycus.org> wrote:

> On 16-05-2012 22:42, Steven Schveighoffer wrote:
>> On Wed, 16 May 2012 16:19:36 -0400, Alex Rønne Petersen <alex@lycus.org>
>> wrote:
>>
>>> Theoretically, yes, practically, not really.
>>>
>>> void myLog(string msg)
>>> {
>>> printf(msg);
>>> }
>>
>> Wait, this should be an error. You need toStringz there.
>>
>> -Steve
>
> Sorry, I meant:
>
> void myLog(string msg)
> {
>      printf(msg.ptr);
> }
>
> (Which works as expected because string literals are null-terminated. This is also how things work when you pass a string literal to a const(char)* value; it just does "literal".ptr.)

No, it doesn't:

myLog("abc"[0..1]); // prints abc instead of the requested a

string is not necessarily a literal.  A literal has a special polysemous type, and special properties.  An ordinary string does not.

-Steve