July 05, 2013
On Fri, 05 Jul 2013 10:13:11 +0100, Dmitry Olshansky <dmitry.olsh@gmail.com> wrote:

> 05-Jul-2013 12:55, Regan Heath пишет:
>> On Thu, 04 Jul 2013 20:15:08 +0100, Dmitry Olshansky
>> <dmitry.olsh@gmail.com> wrote:
>>
>>> 04-Jul-2013 19:00, Regan Heath пишет:
>>>> In fact, you can generalise further.
>>>>
>>>> The meaning of if(x) is "compare the value of x with 0" (in C, C++,
>>>> .. ).
>>>>
>>>> The value of x for a pointer is the address to which it points.
>>>> The value of x for a class reference is the address of the class to
>>>> which it refers.
>>>>
>>>> If D's arrays are reference types,
>>>
>>> They are not. It's a half-reference no wonder it has a bit of
>>> schizophrenia now and then.
>>
>> True.  The struct which contains the ptr and length is actually a value
>> type.  I think conceptually however we should be thinking of them as
>> reference types, because.. the array struct is effectively a lightweight
>> wrapper (adding length) around a reference type (ptr).
>>
>>>   then IMO they should exhibit the same
>>>> behaviour.
>>>>
>>>
>>> The behavior should be the most useful and since arr.length != 0 is
>>> what 99% of time a programmer wants to check.
>>
>> IMO, the behaviour should be consistent.  If you code if (x) then the
>> compiler will compare 'x' (not a property of x) to 0.  Doing anything
>> else would be inconsistent and unexpected to anyone from a C background.
>
> Then since slices compared to null by your logic means both ptr and length equal 0. Completely broken idea hence I'd simply propose to disable it.

I think I need to clarify.

I am making 3 statements here:

1. Arrays are a thin wrapper around a reference type (ptr) which add safety.  W
2. When you have a thin wrapper you should treat operations on the wrapper as the wrapped object in the general case.
3. if (x) should compare x to 0.

Given those statements I have come to the conclusion that if (x) on an array should compare x.ptr to 0.

Which of my statements do you disagree with, and why?

R

-- 
Using Opera's revolutionary email client: http://www.opera.com/mail/
July 05, 2013
On Fri, 05 Jul 2013 10:17:02 +0100, Jonathan M Davis <jmdavisProg@gmx.com> wrote:

> On Friday, July 05, 2013 11:01:17 TommiT wrote:
>> On Thursday, 4 July 2013 at 19:15:09 UTC, Dmitry Olshansky wrote:
>> > 04-Jul-2013 19:00, Regan Heath пишет:
>> >> In fact, you can generalise further.
>> >>
>> >> The meaning of if(x) is "compare the value of x with 0" (in C,
>> >> C++, .. ).
>> >>
>> >> The value of x for a pointer is the address to which it points.
>> >> The value of x for a class reference is the address of the
>> >> class to
>> >> which it refers.
>> >>
>> >> If D's arrays are reference types,
>> >
>> > They are not. It's a half-reference no wonder it has a bit of
>> > schizophrenia now and then.
>>
>> What do you mean by D's dynamic arrays being half-reference
>> types? And what kind of "schizophrenia" do exhibit?
>
> Okay. Take this function.
>
> void foo(T)(T bar)
> {
>     bar.mutateMe();
> }
>
> If T is a reference type, then the argument passed to foo will be mutated. If
> T is a value type, it won't be. But with arrays, it depends. If you alter
> bar's length in any way, it won't have any effect on the array that you passed
> to foo. However, if you alter any of bar's elements, then it _will_ alter the
> array that was passed in. So, arrays are sort of a half-reference type rather
> than a reference type or a value type.

I think it is simpler to think of arrays as a struct with 2 members (ptr and length) and this struct is/as a value type.  Then it all simply makes sense.

R

-- 
Using Opera's revolutionary email client: http://www.opera.com/mail/
July 05, 2013
On Friday, July 05, 2013 10:26:09 Regan Heath wrote:
> I think it is simpler to think of arrays as a struct with 2 members (ptr and length) and this struct is/as a value type.  Then it all simply makes sense.

I'm not saying that it can't be understood. It's just that the semantics are a bit unique, and while it works just fine, it does tend to cause confusion for many people (at least at first).

- Jonathan M Davis
July 05, 2013
05-Jul-2013 13:24, Regan Heath пишет:
> On Fri, 05 Jul 2013 10:13:11 +0100, Dmitry Olshansky
> <dmitry.olsh@gmail.com> wrote:
>
>> 05-Jul-2013 12:55, Regan Heath пишет:
>>> On Thu, 04 Jul 2013 20:15:08 +0100, Dmitry Olshansky
>>> <dmitry.olsh@gmail.com> wrote:
>>>
>>>> 04-Jul-2013 19:00, Regan Heath пишет:
>>>>> In fact, you can generalise further.
>>>>>
>>>>> The meaning of if(x) is "compare the value of x with 0" (in C, C++,
>>>>> .. ).
>>>>>
>>>>> The value of x for a pointer is the address to which it points.
>>>>> The value of x for a class reference is the address of the class to
>>>>> which it refers.
>>>>>
>>>>> If D's arrays are reference types,
>>>>
>>>> They are not. It's a half-reference no wonder it has a bit of
>>>> schizophrenia now and then.
>>>
>>> True.  The struct which contains the ptr and length is actually a value
>>> type.  I think conceptually however we should be thinking of them as
>>> reference types, because.. the array struct is effectively a lightweight
>>> wrapper (adding length) around a reference type (ptr).
>>>
>>>>   then IMO they should exhibit the same
>>>>> behaviour.
>>>>>
>>>>
>>>> The behavior should be the most useful and since arr.length != 0 is
>>>> what 99% of time a programmer wants to check.
>>>
>>> IMO, the behaviour should be consistent.  If you code if (x) then the
>>> compiler will compare 'x' (not a property of x) to 0.  Doing anything
>>> else would be inconsistent and unexpected to anyone from a C background.
>>
>> Then since slices compared to null by your logic means both ptr and
>> length equal 0. Completely broken idea hence I'd simply propose to
>> disable it.
>
> I think I need to clarify.
>
> I am making 3 statements here:
>
> 1. Arrays are a thin wrapper around a reference type (ptr) which add
> safety.

Rather it packs 2 pointers (pair: ptr, ptr+len), modeling the region in between.
No matter how we look at it, it doesn't overlap with most of pointer operations except for indexing. In my opinion it can't be framed as a thin wrapper around _one_ pointer.

> 2. When you have a thin wrapper you should treat operations on the
> wrapper as the wrapped object in the general case.

Continuation of the above stretch.
To be a true wrapper it has to support only the same or subset of operations. For instance arrays have slicing operation hence it's more then that.

> 3. if (x) should compare x to 0.

This one is consistent.

> Given those statements I have come to the conclusion that if (x) on an
> array should compare x.ptr to 0.

I'd agree if arrays did decay to pointers or integers on demand (implicit conversion).

> Which of my statements do you disagree with, and why?
>
> R
>


-- 
Dmitry Olshansky
July 05, 2013
On Friday, 5 July 2013 at 10:39:38 UTC, Dmitry Olshansky wrote:
> 05-Jul-2013 13:24, Regan Heath пишет:
>> Given those statements I have come to the conclusion that if (x) on an
>> array should compare x.ptr to 0.
>
> I'd agree if arrays did decay to pointers or integers on demand (implicit conversion).

Are you arguing that if(x) shouldn't even compile if x is a slice? If so, I was thinking the same thing. The fact that if(x) compiles makes sense only if you think of slice as a struct which happens to provide a convenience cast(bool) operator (which slice doesn't provide). The meaning of if(x) is obvious if x is a full/real/proper reference type. But since slice is just a half-reference, so the meaning of if(x) for slices is not obvious, and thus, it shouldn't compile.
July 05, 2013
On 07/05/13 12:39, Dmitry Olshansky wrote:
> 05-Jul-2013 13:24, Regan Heath пишет:
>> 1. Arrays are a thin wrapper around a reference type (ptr) which add
>> safety.
> 
> Rather it packs 2 pointers (pair: ptr, ptr+len), modeling the region in between.
> No matter how we look at it, it doesn't overlap with most of pointer operations except for indexing. In my opinion it can't be framed as a thin wrapper around _one_ pointer.

The 'array' term is overloaded and confusing, let's call them "slices".

Slices are nothing but fat pointers; they just carry more information - - the length.

>> 2. When you have a thin wrapper you should treat operations on the wrapper as the wrapped object in the general case.
> 
> Continuation of the above stretch.
> To be a true wrapper it has to support only the same or subset of operations. For instance arrays have slicing operation hence it's more then that.

   ubyte* pointer = null;
   auto slice = pointer[0..42];


>> 3. if (x) should compare x to 0.
> 
> This one is consistent.

Actually, slices should implicitly convert to bool with !!length. "Normal" pointers couldn't do that - because they had no length.

artur
July 05, 2013
On 07/05/13 14:26, Artur Skawina wrote:

> Actually, slices should implicitly convert to bool with !!length. "Normal" pointers couldn't do that - because they had no length.

s/implicitly//

artur
July 05, 2013
"TommiT" <tommitissari@hotmail.com> wrote in message news:cajkpllpdchpphqxhyer@forum.dlang.org...
> On Thursday, 4 July 2013 at 13:32:25 UTC, Steven Schveighoffer wrote:
>> On Thu, 04 Jul 2013 08:52:12 -0400, Regan Heath wrote:
>>> Indeed.  IMO if(arr) should mean if(arr.ptr) .. and I thought it did.. or did this change at some point?
>>
>> No, it should mean if(arr.length).  It means if(arr.ptr) now, and this is incorrect.  [..]
>
> The meaning of if(x) for all x of nullable types has always been if(x != null) probably in all languages.

I completely agree, these three functions should return the same no matter
the input:
bool f(T)(T[] x) { if (x) return true; return false; }
bool g(T)(T[] x) { if (x != null) return true; return false; }
bool h(T)(T[] x) { if (x.length) return true; return false; }

The last two already do.


July 05, 2013
On Fri, 05 Jul 2013 11:39:37 +0100, Dmitry Olshansky <dmitry.olsh@gmail.com> wrote:
> 05-Jul-2013 13:24, Regan Heath пишет:
>> On Fri, 05 Jul 2013 10:13:11 +0100, Dmitry Olshansky
>> <dmitry.olsh@gmail.com> wrote:
>>
>>> 05-Jul-2013 12:55, Regan Heath пишет:
>>>> On Thu, 04 Jul 2013 20:15:08 +0100, Dmitry Olshansky
>>>> <dmitry.olsh@gmail.com> wrote:
>>>>
>>>>> 04-Jul-2013 19:00, Regan Heath пишет:
>>>>>> In fact, you can generalise further.
>>>>>>
>>>>>> The meaning of if(x) is "compare the value of x with 0" (in C, C++,
>>>>>> .. ).
>>>>>>
>>>>>> The value of x for a pointer is the address to which it points.
>>>>>> The value of x for a class reference is the address of the class to
>>>>>> which it refers.
>>>>>>
>>>>>> If D's arrays are reference types,
>>>>>
>>>>> They are not. It's a half-reference no wonder it has a bit of
>>>>> schizophrenia now and then.
>>>>
>>>> True.  The struct which contains the ptr and length is actually a value
>>>> type.  I think conceptually however we should be thinking of them as
>>>> reference types, because.. the array struct is effectively a lightweight
>>>> wrapper (adding length) around a reference type (ptr).
>>>>
>>>>>   then IMO they should exhibit the same
>>>>>> behaviour.
>>>>>>
>>>>>
>>>>> The behavior should be the most useful and since arr.length != 0 is
>>>>> what 99% of time a programmer wants to check.
>>>>
>>>> IMO, the behaviour should be consistent.  If you code if (x) then the
>>>> compiler will compare 'x' (not a property of x) to 0.  Doing anything
>>>> else would be inconsistent and unexpected to anyone from a C background.
>>>
>>> Then since slices compared to null by your logic means both ptr and
>>> length equal 0. Completely broken idea hence I'd simply propose to
>>> disable it.
>>
>> I think I need to clarify.
>>
>> I am making 3 statements here:
>>
>> 1. Arrays are a thin wrapper around a reference type (ptr) which add
>> safety.
>
> Rather it packs 2 pointers (pair: ptr, ptr+len), modeling the region in between.

True, but the actual implementation isn't the issue.  The concept of D's arrays was to wrap pointers in order to make them safer.  So, /conceptually/ an array is a thin wrapper over a pointer.  Concept defines semantics, rather than implementation, IMO :)

>> 2. When you have a thin wrapper you should treat operations on the
>> wrapper as the wrapped object in the general case.
>
> Continuation of the above stretch.
> To be a true wrapper it has to support only the same or subset of operations. For instance arrays have slicing operation hence it's more then that.

To my mind wrappers aren't limited in such a way and can add functionality, the key to me is that they continue to expose the underlying object, which d's arrays do (in various ways).

R

-- 
Using Opera's revolutionary email client: http://www.opera.com/mail/
July 05, 2013
05-Jul-2013 16:26, Artur Skawina пишет:
> On 07/05/13 12:39, Dmitry Olshansky wrote:
>> 05-Jul-2013 13:24, Regan Heath пишет:
>>> 1. Arrays are a thin wrapper around a reference type (ptr) which add
>>> safety.
>>
>> Rather it packs 2 pointers (pair: ptr, ptr+len), modeling the region in between.
>> No matter how we look at it, it doesn't overlap with most of pointer operations except for indexing. In my opinion it can't be framed as a thin wrapper around _one_ pointer.
>
> The 'array' term is overloaded and confusing, let's call them "slices".
>
> Slices are nothing but fat pointers;
> they just carry more information -
> - the length.
>

The interesting fact is that slice introduces a new concept - empty slice. It bears no relation to a view of "wrapped" pointer at all.

(0-pointer is not "empty" it can't be empty it's just invalid)

>>> 2. When you have a thin wrapper you should treat operations on the
>>> wrapper as the wrapped object in the general case.
>>
>> Continuation of the above stretch.
>> To be a true wrapper it has to support only the same or subset of operations. For instance arrays have slicing operation hence it's more then that.
>
>     ubyte* pointer = null;
>     auto slice = pointer[0..42];
>

I'd argue that this creates a slice, but point taken. Slicing aside there this empty notion. My point was the space between 2 pointers != pointer semantically hence doesn't need to behave like one no matter the statement.

It's like saying that an integer is the same as an interval of integers because it only adds an extra length field to a starting point. Concept is different.

>
>>> 3. if (x) should compare x to 0.
>>
>> This one is consistent.
>
> Actually, slices should implicitly convert to bool with !!length.
> "Normal" pointers couldn't do that - because they had no length.
>

Aside of meta-arguments for me it ends like this:
1) disallow if(arr)
2) or make it the same as if(arr.length) as more useful/frequent/meaningful

The first step is required anyway if we are to change things.

-- 
Dmitry Olshansky