std.string.chomp error

2010-08-09 Thread simendsjo

The documentation says
/***
 * Returns s[] sans trailing delimiter[], if any.
 * If delimiter[] is null, removes trailing CR, LF, or CRLF, if any.
 */

To adhere to the documentation, chomp must be changed from:

C[] chomp(C, C1)(C[] s, in C1[] delimiter)
{
if (endsWith(s, delimiter))
{
return s[0 .. $ - delimiter.length];
}
return s;
}

to:

C[] chomp(C, C1)(C[] s, in C1[] delimiter)
{
if (delimiter == null)
  return chomp(s);
else if (endsWith(s, delimiter))
  return s[0 .. $ - delimiter.length];
else
  return s;
}




Re: std.string.chomp error

2010-08-09 Thread Lars T. Kyllingstad
On Mon, 09 Aug 2010 18:58:36 +0200, simendsjo wrote:

> The documentation says
> /***
>   * Returns s[] sans trailing delimiter[], if any. * If delimiter[] is
>   null, removes trailing CR, LF, or CRLF, if any. */
> 
> To adhere to the documentation, chomp must be changed from:
> 
> C[] chomp(C, C1)(C[] s, in C1[] delimiter) {
>  if (endsWith(s, delimiter))
>  {
>  return s[0 .. $ - delimiter.length];
>  }
>  return s;
> }
> 
> to:
> 
> C[] chomp(C, C1)(C[] s, in C1[] delimiter) {
>  if (delimiter == null)
>return chomp(s);
>  else if (endsWith(s, delimiter))
>return s[0 .. $ - delimiter.length];
>  else
>return s;
> }


Either that, or the documentation for it needs to be changed.  Anyway, it 
would be great if you'd report this.

http://d.puremagic.com/issues/

Thanks!

-Lars


Re: std.string.chomp error

2010-08-09 Thread bearophile
Lars T. Kyllingstad:
> Either that, or the documentation for it needs to be changed.  Anyway, it 
> would be great if you'd report this.

A really basic unit testing is able to catch an error like this. This means 
Phobos needs more unit tests.

Stuff that may be added to that unittest:

import std.stdio, std.string;
void main() {
assert(chomp("hello") == "hello");
assert(chomp("hello\n") == "hello");
assert(chomp("hello\r\n") == "hello");
assert(chomp("hello", "") == "hello");
assert(chomp("hello\n", "") == "hello");
assert(chomp("hello\r\n", "") == "hello");
assert(chomp("hello\r\n", "") == "hello");
assert(chomp("helloxxx", "x") == "helloxx");
}


But instead of:
if (delimiter == null)
Is better to write:
if (delimiter.length == 0)
Or:
if (delimiter == "")

See http://d.puremagic.com/issues/show_bug.cgi?id=3889

Bye,
bearophile


Re: std.string.chomp error

2010-08-09 Thread simendsjo

On 09.08.2010 19:16, Lars T. Kyllingstad wrote:

On Mon, 09 Aug 2010 18:58:36 +0200, simendsjo wrote:


The documentation says
/***
   * Returns s[] sans trailing delimiter[], if any. * If delimiter[] is
   null, removes trailing CR, LF, or CRLF, if any. */

To adhere to the documentation, chomp must be changed from:

C[] chomp(C, C1)(C[] s, in C1[] delimiter) {
  if (endsWith(s, delimiter))
  {
  return s[0 .. $ - delimiter.length];
  }
  return s;
}

to:

C[] chomp(C, C1)(C[] s, in C1[] delimiter) {
  if (delimiter == null)
return chomp(s);
  else if (endsWith(s, delimiter))
return s[0 .. $ - delimiter.length];
  else
return s;
}



Either that, or the documentation for it needs to be changed.  Anyway, it
would be great if you'd report this.

http://d.puremagic.com/issues/

Thanks!

-Lars


Ok; http://d.puremagic.com/issues/show_bug.cgi?id=4608


Re: std.string.chomp error

2010-08-09 Thread bearophile
simendsjo:
> Ok; http://d.puremagic.com/issues/show_bug.cgi?id=4608

You seem to have missed my answer :-)

Bye,
bearophile


Re: std.string.chomp error

2010-08-09 Thread simendsjo

On 09.08.2010 23:58, bearophile wrote:

simendsjo:

Ok; http://d.puremagic.com/issues/show_bug.cgi?id=4608


You seem to have missed my answer :-)

Bye,
bearophile


No, but I don't know if it's the documentation or implementation that's 
correct.


Re: std.string.chomp error

2010-08-09 Thread simendsjo

On 09.08.2010 19:34, bearophile wrote:

Lars T. Kyllingstad:

Either that, or the documentation for it needs to be changed.  Anyway, it
would be great if you'd report this.


A really basic unit testing is able to catch an error like this. This means 
Phobos needs more unit tests.

Stuff that may be added to that unittest:

import std.stdio, std.string;
void main() {
 assert(chomp("hello") == "hello");
 assert(chomp("hello\n") == "hello");
 assert(chomp("hello\r\n") == "hello");
 assert(chomp("hello", "") == "hello");
 assert(chomp("hello\n", "") == "hello");
 assert(chomp("hello\r\n", "") == "hello");
 assert(chomp("hello\r\n", "") == "hello");
 assert(chomp("helloxxx", "x") == "helloxx");
}


But instead of:
if (delimiter == null)
Is better to write:
if (delimiter.length == 0)
Or:
if (delimiter == "")

See http://d.puremagic.com/issues/show_bug.cgi?id=3889

Bye,
bearophile


Ahem.. :) Yes, I did miss your answer! How I got fooled by the preview 
pane and never noticed the scrollbar.
I cannot see how your other bug report relates to this though. For 
chomps part it's just an implementation vs. documentation issue.


Re: std.string.chomp error

2010-08-09 Thread bearophile
simendsjo:
> Ahem.. :) Yes, I did miss your answer! How I got fooled by the preview 
> pane and never noticed the scrollbar.

No problem, it happens, don't worry.


> I cannot see how your other bug report relates to this though.

My other bug report is about this line in your code:
 if (delimiter == null)
I don't like it :-)

Bye,
bearophile


Re: std.string.chomp error

2010-08-09 Thread Jonathan M Davis
On Monday, August 09, 2010 16:59:07 bearophile wrote:
> simendsjo:
> > Ahem.. :) Yes, I did miss your answer! How I got fooled by the preview
> > pane and never noticed the scrollbar.
> 
> No problem, it happens, don't worry.
> 
> > I cannot see how your other bug report relates to this though.
> 
> My other bug report is about this line in your code:
>  if (delimiter == null)
> I don't like it :-)
> 
> Bye,
> bearophile

Why, because it should be

if(delimiter is null)


or just

if(!delimiter)


- Jonathan M Davis


Re: std.string.chomp error

2010-08-09 Thread simendsjo

On 10.08.2010 02:09, Jonathan M Davis wrote:

On Monday, August 09, 2010 16:59:07 bearophile wrote:

simendsjo:

Ahem.. :) Yes, I did miss your answer! How I got fooled by the preview
pane and never noticed the scrollbar.


No problem, it happens, don't worry.


I cannot see how your other bug report relates to this though.


My other bug report is about this line in your code:
  if (delimiter == null)
I don't like it :-)

Bye,
bearophile


Why, because it should be

if(delimiter is null)


or just

if(!delimiter)


- Jonathan M Davis


Hehe.. You're a bit beyond my D level right now. At least I now know 
null == false and you can do reference is null :)


Re: std.string.chomp error

2010-08-09 Thread Jonathan M Davis
On Monday, August 09, 2010 17:09:03 simendsjo wrote:
> On 10.08.2010 02:09, Jonathan M Davis wrote:
> > On Monday, August 09, 2010 16:59:07 bearophile wrote:
> >> simendsjo:
> >>> Ahem.. :) Yes, I did miss your answer! How I got fooled by the preview
> >>> pane and never noticed the scrollbar.
> >> 
> >> No problem, it happens, don't worry.
> >> 
> >>> I cannot see how your other bug report relates to this though.
> >> 
> >> My other bug report is about this line in your code:
> >>   if (delimiter == null)
> >> 
> >> I don't like it :-)
> >> 
> >> Bye,
> >> bearophile
> > 
> > Why, because it should be
> > 
> > if(delimiter is null)
> > 
> > 
> > or just
> > 
> > if(!delimiter)
> > 
> > 
> > - Jonathan M Davis
> 
> Hehe.. You're a bit beyond my D level right now. At least I now know
> null == false and you can do reference is null :)

IIRC, you're not really supposed to do "delim == null" but rather us "delim is 
null" or shorten to to just "!delim". Why, I don't recall off the top of my 
head, 
but it might be because "delim == null" would be calling Object.opEquals(), and 
there's no need for that function call (though fortunately "delim == null" 
translates to Object.opEquals(delim, null) rather than delim.opEquals(null) 
which avoids issues where the lhs is null and causes it to go boom).

In either case, for null checks, I'd suggest either just using the reference by 
itself or to explictly use "is null" if you want the extra clarity.

- Jonathan M Davis


Re: std.string.chomp error

2010-08-09 Thread bearophile
Jonathan M Davis:
> Why, because it should be
> 
> if(delimiter is null)
> 
> 
> or just
> 
> if(!delimiter)

if (delimiter.length == 0)
Or 
if (!delimiter.length)

Bye,
bearophile


Re: std.string.chomp error

2010-08-09 Thread simendsjo

On 10.08.2010 03:08, bearophile wrote:

Jonathan M Davis:

Why, because it should be

if(delimiter is null)


or just

if(!delimiter)


if (delimiter.length == 0)
Or
if (!delimiter.length)

Bye,
bearophile


Isn't that very different things? You cannot use .length if delimiter is 
null.




Re: std.string.chomp error

2010-08-09 Thread Jonathan M Davis
On Monday, August 09, 2010 18:12:11 simendsjo wrote:
> On 10.08.2010 03:08, bearophile wrote:
> > Jonathan M Davis:
> >> Why, because it should be
> >> 
> >> if(delimiter is null)
> >> 
> >> 
> >> or just
> >> 
> >> if(!delimiter)
> > 
> > if (delimiter.length == 0)
> > Or
> > if (!delimiter.length)
> > 
> > Bye,
> > bearophile
> 
> Isn't that very different things? You cannot use .length if delimiter is
> null.

If that's what you're looking for, then the proper thing to do would be to 
import std.array and do this

if(delimiter.empty)

It wille handle both null and length == 0 cases. Not to mention, it's much more 
range-y that way.

- Jonathan M Davis


Re: std.string.chomp error

2010-08-10 Thread Lars T. Kyllingstad
On Mon, 09 Aug 2010 17:35:56 -0700, Jonathan M Davis wrote:

> On Monday, August 09, 2010 17:09:03 simendsjo wrote:
>> On 10.08.2010 02:09, Jonathan M Davis wrote:
>> > On Monday, August 09, 2010 16:59:07 bearophile wrote:
>> >> simendsjo:
>> >>> Ahem.. :) Yes, I did miss your answer! How I got fooled by the
>> >>> preview pane and never noticed the scrollbar.
>> >> 
>> >> No problem, it happens, don't worry.
>> >> 
>> >>> I cannot see how your other bug report relates to this though.
>> >> 
>> >> My other bug report is about this line in your code:
>> >>   if (delimiter == null)
>> >> 
>> >> I don't like it :-)
>> >> 
>> >> Bye,
>> >> bearophile
>> > 
>> > Why, because it should be
>> > 
>> > if(delimiter is null)
>> > 
>> > 
>> > or just
>> > 
>> > if(!delimiter)
>> > 
>> > 
>> > - Jonathan M Davis
>> 
>> Hehe.. You're a bit beyond my D level right now. At least I now know
>> null == false and you can do reference is null :)
> 
> IIRC, you're not really supposed to do "delim == null" but rather us
> "delim is null" or shorten to to just "!delim". Why, I don't recall off
> the top of my head, but it might be because "delim == null" would be
> calling Object.opEquals(), and there's no need for that function call
> (though fortunately "delim == null" translates to Object.opEquals(delim,
> null) rather than delim.opEquals(null) which avoids issues where the lhs
> is null and causes it to go boom).
> 
> In either case, for null checks, I'd suggest either just using the
> reference by itself or to explictly use "is null" if you want the extra
> clarity.

No, using 'is' won't work.  Check this out:

  int[] a;
  assert (a == null);
  assert (a is null);

  a = new int[10];
  a.length = 0;
  assert (a == null);
  assert (a !is null);

The thing is, '==' tests whether two arrays are equal, that is, that they 
are equally long and that their elements are equal.  Any empty array is 
equal to null -- in fact, in this context 'null' is just a way of 
denoting an empty array that doesn't point to any particular memory block 
(i.e. hasn't been initialised yet).

  // This is what '==' does
  bool mimicEquals(int[] a, int[] b)
  {
  if (a.length != b.length) return false;
  foreach (i; 0 .. a.length) if (a[i] != b[i]) return false;
  return true;
  }

'is', on the other hand, tests whether two arrays are identical, i.e. 
that they have the same length and *refer to the same piece of memory*.

  // This is (sort of) what 'is' does
  bool mimicIs(int[] a, int[] b)
  {
 return (a.ptr == b.ptr  &&  a.length == b.length);
  }

-Lars


Re: std.string.chomp error

2010-08-10 Thread Jonathan M Davis
On Tuesday 10 August 2010 00:30:37 Lars T. Kyllingstad wrote:
> No, using 'is' won't work.  Check this out:
> 
>   int[] a;
>   assert (a == null);
>   assert (a is null);
> 
>   a = new int[10];
>   a.length = 0;
>   assert (a == null);
>   assert (a !is null);
> 
> The thing is, '==' tests whether two arrays are equal, that is, that they
> are equally long and that their elements are equal.  Any empty array is
> equal to null -- in fact, in this context 'null' is just a way of
> denoting an empty array that doesn't point to any particular memory block
> (i.e. hasn't been initialised yet).
> 
>   // This is what '==' does
>   bool mimicEquals(int[] a, int[] b)
>   {
>   if (a.length != b.length) return false;
>   foreach (i; 0 .. a.length) if (a[i] != b[i]) return false;
>   return true;
>   }
> 
> 'is', on the other hand, tests whether two arrays are identical, i.e.
> that they have the same length and *refer to the same piece of memory*.
> 
>   // This is (sort of) what 'is' does
>   bool mimicIs(int[] a, int[] b)
>   {
>  return (a.ptr == b.ptr  &&  a.length == b.length);
>   }
> 
> -Lars

Actually, it looks to me that that's an argument for using is for checking for 
null rather than ==, since == isn't really going to tell you. The fact that == 
doesn't care about whether an array is null makes it not work for checking for 
whether an array is null.

1. As I understand it, using is instead of == is for all references, not just 
arrays and their bizarre pseudo-null state. Using is with a class will avoid 
calling opEquals() and does exactly what you want when checking whether a class 
reference is null.

2. For arrays, if you want to check whether it really is null, then you _must_ 
use is, because == obviously isn't going to tell you. It'll just lump empty 
arrays in with null ones. For instance, if you want to check that an array has 
never been initialized or that it has been set to null and never set to 
something else, then you need to use is.

3. On the other hand, if what you really care about is checking whether an 
array 
has any elements and you don't care about whether it's null or not, then the 
empty function/property would be the better way to go. It's quite explicit, and 
it's more generic, doing things the way that ranges are done.

Personally, I think that the way that null is handled with arrays and 
associative arrays is a poor design choice (if they're null, they should be 
null 
until you assign to them with new rather than this whole null but not null 
nonsense), but we're stuck with it I guess.

- Jonathan M Davis


Re: std.string.chomp error

2010-08-10 Thread Lars T. Kyllingstad
On Tue, 10 Aug 2010 01:48:17 -0700, Jonathan M Davis wrote:

> On Tuesday 10 August 2010 00:30:37 Lars T. Kyllingstad wrote:
>> No, using 'is' won't work.  Check this out:
>> 
>>   int[] a;
>>   assert (a == null);
>>   assert (a is null);
>> 
>>   a = new int[10];
>>   a.length = 0;
>>   assert (a == null);
>>   assert (a !is null);
>> 
>> The thing is, '==' tests whether two arrays are equal, that is, that
>> they are equally long and that their elements are equal.  Any empty
>> array is equal to null -- in fact, in this context 'null' is just a way
>> of denoting an empty array that doesn't point to any particular memory
>> block (i.e. hasn't been initialised yet).
>> 
>>   // This is what '==' does
>>   bool mimicEquals(int[] a, int[] b)
>>   {
>>   if (a.length != b.length) return false; foreach (i; 0 ..
>>   a.length) if (a[i] != b[i]) return false; return true;
>>   }
>> 
>> 'is', on the other hand, tests whether two arrays are identical, i.e.
>> that they have the same length and *refer to the same piece of memory*.
>> 
>>   // This is (sort of) what 'is' does
>>   bool mimicIs(int[] a, int[] b)
>>   {
>>  return (a.ptr == b.ptr  &&  a.length == b.length);
>>   }
>> 
>> -Lars
> 
> Actually, it looks to me that that's an argument for using is for
> checking for null rather than ==, since == isn't really going to tell
> you. The fact that == doesn't care about whether an array is null makes
> it not work for checking for whether an array is null.

I guess it depends on what behaviour you're after.  In the present case, 
if you want chomp(a, null) and chomp(a, "") to do the same thing, then 
you should use '=='.  If you want chomp(a, "") to simply do nothing, use 
'is'.  I just figured that the former was the desired behaviour here.  If 
it isn't, I agree with you. :)


> 1. As I understand it, using is instead of == is for all references, not
> just arrays and their bizarre pseudo-null state. Using is with a class
> will avoid calling opEquals() and does exactly what you want when
> checking whether a class reference is null.

Fun fact: Actually, 'is' works for any type.

  assert (1 is 1);

As I've understood it, 'a is b' is true if the variables a and b contain 
the exact same bits.  If a and b are value types, this must mean they 
have the same value, and if they are references (including arrays), it 
means they refer to the same data.


> 2. For arrays, if you want to check whether it really is null, then you
> _must_ use is, because == obviously isn't going to tell you. It'll just
> lump empty arrays in with null ones. For instance, if you want to check
> that an array has never been initialized or that it has been set to null
> and never set to something else, then you need to use is.
> 
> 3. On the other hand, if what you really care about is checking whether
> an array has any elements and you don't care about whether it's null or
> not, then the empty function/property would be the better way to go.
> It's quite explicit, and it's more generic, doing things the way that
> ranges are done.

I totally agree with you.  Lately, I have started using "empty" (as well 
as the other range primitives) for arrays myself.  I just disagreed that 
'is' would produce what I perceived to be the right behaviour for the 
function in question.  But that perception may well be wrong. ;)


> Personally, I think that the way that null is handled with arrays and
> associative arrays is a poor design choice (if they're null, they should
> be null until you assign to them with new rather than this whole null
> but not null nonsense), but we're stuck with it I guess.

There, I don't agree with you.  Arrays are a sort of pseudo-reference 
type, so I don't mind 'null' being a sort of pseudo-null in that 
context.  Actually, I find it to be quite elegant.  It's a matter of 
taste, I guess.

-Lars


Re: std.string.chomp error

2010-08-10 Thread bearophile
Lars T. Kyllingstad:
> There, I don't agree with you.  Arrays are a sort of pseudo-reference 
> type, so I don't mind 'null' being a sort of pseudo-null in that 
> context.  Actually, I find it to be quite elegant.  It's a matter of 
> taste, I guess.

I suggest you to write down the things you don't like and the design you desire 
here.

Bye,
bearophile


Re: std.string.chomp error

2010-08-10 Thread Lars T. Kyllingstad
On Tue, 10 Aug 2010 07:50:34 -0400, bearophile wrote:

> Lars T. Kyllingstad:
>> There, I don't agree with you.  Arrays are a sort of pseudo-reference
>> type, so I don't mind 'null' being a sort of pseudo-null in that
>> context.  Actually, I find it to be quite elegant.  It's a matter of
>> taste, I guess.
> 
> I suggest you to write down the things you don't like and the design you
> desire here.

??

I like how it is designed now, that was my point.

-Lars


Re: std.string.chomp error

2010-08-10 Thread bearophile
Lars T. Kyllingstad:
> I like how it is designed now, that was my point.

Sorry, I misread you.


Re: std.string.chomp error

2010-08-10 Thread Jonathan M Davis
On Tuesday 10 August 2010 02:34:33 Lars T. Kyllingstad wrote:
> I guess it depends on what behaviour you're after.  In the present case,
> if you want chomp(a, null) and chomp(a, "") to do the same thing, then
> you should use '=='.  If you want chomp(a, "") to simply do nothing, use
> 'is'.  I just figured that the former was the desired behaviour here.  If
> it isn't, I agree with you. :)

I was really talking about the general case rather than chomp() in specific, 
but's fine with me if "" and null are treated the same here, I suppose. Still,  
I 
really don't like it when null and empty is treated the same way (in D or 
anything else). There's a difference between something not existing and it 
existing but not having anything in it. But, as I said, we're stuck with the 
way 
it is in D.

- Jonathan M Davis