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


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