May 16, 2012
On Wed, 16 May 2012 17:11:58 -0400, deadalnix <deadalnix@gmail.com> wrote:

> 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.

OK, so it's allowed to be 0 and not-null.  doesn't this lead to the confusing semantics you were talking about?

What about this?

int[] arr;
arr.reserve(10000);

int[] arr2 = [1,2,3];
arr2 = arr; // now length has been *set* to 0, should it also be nulled?

But I want arr2 and arr to point at the same thing, maybe I'm not using arr anymore.  Maybe I returned it from a function, and I no longer have access to arr.

-Steve
May 16, 2012
On 16-05-2012 23:09, Steven Schveighoffer wrote:
> 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

I was referring to: myLog("abc");

When you start bringing slicing into the mix, you're bound to make C interop harder and more error-prone because of null-termination.

-- 
Alex Rønne Petersen
alex@lycus.org
http://lycus.org
May 16, 2012
On 05/16/2012 11:08 PM, deadalnix wrote:
> Le 16/05/2012 22:19, Alex Rønne Petersen a écrit :
>>  ...
>> 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.

It is not unsafe, it is invalid.
May 16, 2012
On Wed, May 16, 2012 at 11:22:48PM +0200, Alex Rønne Petersen wrote:
> On 16-05-2012 23:09, Steven Schveighoffer wrote:
> >On Wed, 16 May 2012 17:06:41 -0400, Alex Rønne Petersen <alex@lycus.org> wrote:
[...]
> >>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
> 
> I was referring to: myLog("abc");
> 
> When you start bringing slicing into the mix, you're bound to make C interop harder and more error-prone because of null-termination.
[...]

I think his point is that myLog is poorly written because it declares itself to have a string parameter, yet does not function properly when called with a string that isn't NULL-terminated (e.g. a string slice).


T

-- 
Let's not fight disease by killing the patient. -- Sean 'Shaleh' Perry
May 16, 2012
On Wednesday, May 16, 2012 19:52:07 Alex Rønne Petersen wrote:
> I guess we can conclude that one should not use 'null' or 'is' for arrays unless absolutely necessary. '[]' and '==' should probably do for the majority of code.

The only reason to use is is if you're checking for identity rather than equality. == checks for equality. It should be clear when you need one or the other.

null and [] are essentially equivalent, so it doesn't really matter which you use.

However, I'd argue that using == with null or [] is a bad move, because it tends to show a lack of understanding, simply because it's so natural for people to try and check whether something is null by comparing against ==, and that _doesn't work_. So, if you want to check whether an array is empty, use empty or length == 0, whereas if you want to check whether an array is null, then use is null.

But aside from the issues of clarity surrounding checking whether an array is empty by using == null or == [], I think that it's quite clear when == or is should be used. If it's not, it's because you don't understand the differences between the two.

- Jonathan M Davis
May 16, 2012
On Wednesday, May 16, 2012 09:18:38 Steven Schveighoffer wrote:
> but I still think we should discourage using null as a sentinel, it leads to confusing code.

If null were actually properly differentiated from empty, then this wouldn't be a problem, but it's not. It _should_ be possible to treat null as a sentinel. The fact that it causes issues is a major flaw in the language IMHO. But given that flaw, it does very quickly become error-prone to use null as a sentinel. In general, I'd say that the only reasonable place to do so is when returning an array (and especially a string) from a function. The return value can then be immeditely checked with is null before it has the chance to have something happen to it which could cause it to be empty but non-null.

- Jonathan M Davis
May 17, 2012
On 16-05-2012 00:20, deadalnix wrote:
> Le 15/05/2012 21:57, Andrew Wiley a écrit :
>> On Tue, May 15, 2012 at 11:46 AM, deadalnix <deadalnix@gmail.com
>> <mailto:deadalnix@gmail.com>> wrote:
>>
>> Le 15/05/2012 18:19, Gor Gyolchanyan a écrit :
>>
>>
>>
>> On Tue, May 15, 2012 at 7:51 PM, Christophe
>> <travert@phare.normalesup.org
>> <mailto:travert@phare.normalesup.org>
>> <mailto:travert@phare.__normalesup.org
>> <mailto:travert@phare.normalesup.org>>> wrote:
>>
>> using printf will lead to a bug each time the programmer
>> forget the
>> trailing
>> \0.
>>
>>
>> First of all, printf shouldn't be used! There's writef and it's
>> superior
>> to printf in any way!
>> Second of all, if the zero-termination of literals are to be
>> removed,
>> the literals will no longer be accepted as a pointer to a character.
>> The appropriate type mismatch error will force the user to use
>> toUTF8z
>> to get ht e zero-terminated utf-8 version of the original string.
>> In case it's a literal, one could use the compile-time version of
>> toUTF8z to avoid run-time overhead.
>> This all doesn't sound like a bad idea to me. I don't see any
>> security
>> or performance flaws in this scheme.
>> --
>> Bye,
>> Gor Gyolchanyan.
>>
>>
>> May god ear you !
>>
>>
>> Unfortunately, using writef/writefln would make DRuntime depend on
>> Phobos, which is unacceptable.
>>
>
> druntime isn't supposed to printf stuff.

It's called debugging. ;)

-- 
Alex Rønne Petersen
alex@lycus.org
http://lycus.org
May 17, 2012
Le 16/05/2012 23:15, Steven Schveighoffer a écrit :
> On Wed, 16 May 2012 17:11:58 -0400, deadalnix <deadalnix@gmail.com> wrote:
>
>> 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.
>
> OK, so it's allowed to be 0 and not-null. doesn't this lead to the
> confusing semantics you were talking about?
>
> What about this?
>
> int[] arr;
> arr.reserve(10000);
>
> int[] arr2 = [1,2,3];
> arr2 = arr; // now length has been *set* to 0, should it also be nulled?
>
> But I want arr2 and arr to point at the same thing, maybe I'm not using
> arr anymore. Maybe I returned it from a function, and I no longer have
> access to arr.
>
> -Steve

That make sense :D
May 17, 2012
On Thu, 17 May 2012 00:08:49 +0100, Jonathan M Davis <jmdavisProg@gmx.com> wrote:

> On Wednesday, May 16, 2012 09:18:38 Steven Schveighoffer wrote:
>> but I still think we should discourage using null as a
>> sentinel, it leads to confusing code.
>
> If null were actually properly differentiated from empty, then this wouldn't be
> a problem, but it's not. It _should_ be possible to treat null as a sentinel.
> The fact that it causes issues is a major flaw in the language IMHO. But given
> that flaw, it does very quickly become error-prone to use null as a sentinel.
> In general, I'd say that the only reasonable place to do so is when returning
> an array (and especially a string) from a function. The return value can then
> be immeditely checked with is null before it has the chance to have something
> happen to it which could cause it to be empty but non-null.

I want to re-re-re-register my dismay in the situation also.  For me it always comes back to.. I can do it with a pointer.. a pointer!  Why not an array?!?

R

-- 
Using Opera's revolutionary email client: http://www.opera.com/mail/
May 18, 2012
"Steven Schveighoffer" , dans le message (digitalmars.D:167556), a
> toStringz can allocate a new block in order to ensure 0 gets added.  This is ludicrous!
> 
> You are trying to tell me that any time I want to call a C function with a string literal, I have to first heap-allocate it, even though I *know* it's safe.

How about "mystring\0".ptr ?