April 10, 2006
Regan Heath wrote:
> On Mon, 10 Apr 2006 11:58:09 +1000, Derek Parnell <derek@psych.ward> wrote:
> 
>> On Mon, 10 Apr 2006 12:23:06 +1200, Regan Heath wrote:
>>
>>> Take this code:
>>>
>>> void main()
>>> {
>>>     //..open a file, read line for line, on each line:
>>>
>>>     for(int i = 0; i < line.length-2; i++) {
>>>         if (line[i..i+2] != "||") continue;
>>>         //..etc..
>>>     }
>>> }
>>>
>>> There is a subtle bug. On all lines with a length of 0 or 1 it will give
>>> the following error:
>>>
>>> Error: ArrayBoundsError line_length.d(6)
>>>
>>> The problem is of course the statement "i < line.length-2". line.length  is
>>> unsigned, and when you - 2 from an unsigned value.. well lets just say
>>> that it's bigger than the actual length of the line - 2.
>>>
>>> Of course there are plently of other ways to code this, perhaps using
>>> foreach, but that's not the point. The point is that this code  _can_ be
>>> written and on the surface looks fine. Not even -w (warnings) spots the
>>> signed/unsigned problem. At the very least can we get a warning for  this?
>>
>>
>> I too have tripped up on this 'bug' and it is very annoying and  surprising.
>>
>> However your approach to the problem might need to change...as you state  -
>> "On all lines with a length of 0 or 1 it will give the following  error..."
>> - and this is because the test that you are performing is only applicable
>> to lines with two or more characters in them ... so make that condition a
>> part of the algorithm ...
>>
>>   if (line.length >= 2) {
>>     for(int i = 0; i < line.length-2; i++) {
>>       if (line[i..i+2] != "||") continue;
>>       //..etc..
>>     }
>>   }
>>   else {
>>      // do something for short lines...
>>   }
> 
> 
> Thanks Derek, that's exactly what I did.
> 
> The point of this post isn't to get help with one specific problem but  rather to ask whether there is a solution to the underlying problem  behaviour. I suspect this behaviour will be the source of many bugs to  come and I wonder if there is a way to avoid them.

First, how come you don't use this code?

	for (int i=0; i<line.length-2; i++)
	{
		if (line[i..i] == "|")
			if (line[i+1..i+1] == "|")
				continue;
	}

It should be more than twice as fast.

Second, isn't your code just an excellent example of why we have bounds checking in D in the first place?

I think the obvious and clear-for-the-reader solution is to wrap that code in an if:

	if (line.length > 1)
	{
		// the above code here
	}

I can't see what would be wrong with that.
April 10, 2006
In article <ops7rncsol23k2f5@nrage.netwin.co.nz>, Regan Heath says...
>
>Take this code:
>
>void main()
>{
>	//..open a file, read line for line, on each line:
>
>	for(int i = 0; i < line.length-2; i++) {
>		if (line[i..i+2] != "||") continue;
>		//..etc..
>	}
>}
>
>
>There is a subtle bug. On all lines with a length of 0 or 1 it will give the following error:
>
>Error: ArrayBoundsError line_length.d(6)
>
>
>The problem is of course the statement "i < line.length-2". line.length is unsigned, and when you - 2 from an unsigned value.. well lets just say that it's bigger than the actual length of the line - 2.
>
>
>Of course there are plently of other ways to code this, perhaps using foreach, but that's not the point. The point is that this code  _can_ be written and on the surface looks fine. Not even -w (warnings) spots the signed/unsigned problem. At the very least can we get a warning for this?
>
>Regan

I see the "gotcha" here, and whether conversions should be done is an interesting question.  But I wanted to propose a slightly different solution.

> for(int i = 0; i+2 < line.length; i++) {

Since you are reference "i+2" in the expression, that is really the value what you need to be in the [0..length) range.

More generally, always do the arithmetic with the signed variables in cases like this if there is a possibility of wraparound.

But if the automatic conversions were specified to do uint->int that would also be fine with me.

One can also imagine a language with the following inequalities:

+>  unsigned greater-than
+<  unsigned less than
->  signed greater than
-<  signed less than
+>= unsigned greater-or-equal
etc

This would not replace the current >, <, but would essentially just be shorthand for existing expressions:

(A +> B) is the same as (cast(uint)A > cast(uint)B)

.. and so on, except that uint, ulong, ushort, etc would be chosen as needed.

Is this worth doing?  Maybe - it's not a big deal to me, but the signed/unsigned question does represent a common gotcha in certain expressions.

Kevin


April 10, 2006
On Mon, 10 Apr 2006 17:42:33 +0300, Georg Wrede <georg.wrede@nospam.org> wrote:
> Regan Heath wrote:
>> On Mon, 10 Apr 2006 11:58:09 +1000, Derek Parnell <derek@psych.ward> wrote:
>>
>>> On Mon, 10 Apr 2006 12:23:06 +1200, Regan Heath wrote:
>>>
>>>> Take this code:
>>>>
>>>> void main()
>>>> {
>>>>     //..open a file, read line for line, on each line:
>>>>
>>>>     for(int i = 0; i < line.length-2; i++) {
>>>>         if (line[i..i+2] != "||") continue;
>>>>         //..etc..
>>>>     }
>>>> }
>>>>
>>>> There is a subtle bug. On all lines with a length of 0 or 1 it will give
>>>> the following error:
>>>>
>>>> Error: ArrayBoundsError line_length.d(6)
>>>>
>>>> The problem is of course the statement "i < line.length-2". line.length  is
>>>> unsigned, and when you - 2 from an unsigned value.. well lets just say
>>>> that it's bigger than the actual length of the line - 2.
>>>>
>>>> Of course there are plently of other ways to code this, perhaps using
>>>> foreach, but that's not the point. The point is that this code  _can_ be
>>>> written and on the surface looks fine. Not even -w (warnings) spots the
>>>> signed/unsigned problem. At the very least can we get a warning for  this?
>>>
>>>
>>> I too have tripped up on this 'bug' and it is very annoying and  surprising.
>>>
>>> However your approach to the problem might need to change...as you state  -
>>> "On all lines with a length of 0 or 1 it will give the following  error..."
>>> - and this is because the test that you are performing is only applicable
>>> to lines with two or more characters in them ... so make that condition a
>>> part of the algorithm ...
>>>
>>>   if (line.length >= 2) {
>>>     for(int i = 0; i < line.length-2; i++) {
>>>       if (line[i..i+2] != "||") continue;
>>>       //..etc..
>>>     }
>>>   }
>>>   else {
>>>      // do something for short lines...
>>>   }
>>   Thanks Derek, that's exactly what I did.
>>  The point of this post isn't to get help with one specific problem but  rather to ask whether there is a solution to the underlying problem  behaviour. I suspect this behaviour will be the source of many bugs to  come and I wonder if there is a way to avoid them.
>
> First, how come you don't use this code?
>
> 	for (int i=0; i<line.length-2; i++)
> 	{
> 		if (line[i..i] == "|")
> 			if (line[i+1..i+1] == "|")
> 				continue;
> 	}
>
> It should be more than twice as fast.

Because speed wasn't important in this case (once-off console app)

> Second, isn't your code just an excellent example of why we have bounds checking in D in the first place?

Bounds checking certainly helps.

> I think the obvious and clear-for-the-reader solution is to wrap that code in an if:
>
> 	if (line.length > 1)
> 	{
> 		// the above code here
> 	}
>
> I can't see what would be wrong with that.

See my reply to Derek for why I think it's 'wrong'.

Regan
April 10, 2006
On Mon, 10 Apr 2006 18:51:00 +1000, Derek Parnell <derek@psych.ward> wrote:
> On Mon, 10 Apr 2006 17:54:25 +1000, S. Chancellor <dnewsgr@mephit.kicks-ass.org> wrote:
>
>
>> Erps, I should skim your post better.  Yeah that's a problem, you can fix it without the other if though.
>>
>> for(int i = 0; i + 2 < line.length; i++) {
>>
>>
>> Or am I still missing something?  Hehe.
>
> No, that is fine and along the same lines as the original code. As is
>
>     for(int i = 0; i < (cast(int)line.length)-2; i++) {
>
> however I still prefer telling the code reader what I'm doing etc... in clear, simple code. Although your code will work, it just isn't as clear at first glance as
>
>    if (line.length >= 2)
>    {
>       ...
>    }
>
> but of course an even better way (IMHO) ...
>
>      int posn = std.string.find(line, "||");
>      if (posn >= 0)
>      {
>          // etc ....
>      }

In my case there were several || on the lines, eg.

..etc..||<A>_desc||..etc..||<B>_desc||..etc..

and I'm actually rewriting them as:

..etc..||thing(<A>_desc)||..etc..||thing(<B>_desc)||..etc..

but, yeah, it's possible to use find. :)

Regan

April 10, 2006
On Mon, 10 Apr 2006 16:28:00 +0000 (UTC), Kevin Bealer <Kevin_member@pathlink.com> wrote:
> In article <ops7rncsol23k2f5@nrage.netwin.co.nz>, Regan Heath says...
>>
>> Take this code:
>>
>> void main()
>> {
>> 	//..open a file, read line for line, on each line:
>>
>> 	for(int i = 0; i < line.length-2; i++) {
>> 		if (line[i..i+2] != "||") continue;
>> 		//..etc..
>> 	}
>> }
>>
>>
>> There is a subtle bug. On all lines with a length of 0 or 1 it will give
>> the following error:
>>
>> Error: ArrayBoundsError line_length.d(6)
>>
>>
>> The problem is of course the statement "i < line.length-2". line.length is
>> unsigned, and when you - 2 from an unsigned value.. well lets just say
>> that it's bigger than the actual length of the line - 2.
>>
>>
>> Of course there are plently of other ways to code this, perhaps using
>> foreach, but that's not the point. The point is that this code  _can_ be
>> written and on the surface looks fine. Not even -w (warnings) spots the
>> signed/unsigned problem. At the very least can we get a warning for this?
>>
>> Regan
>
> I see the "gotcha" here, and whether conversions should be done is an
> interesting question.  But I wanted to propose a slightly different solution.
>
>> for(int i = 0; i+2 < line.length; i++) {
>
> Since you are reference "i+2" in the expression, that is really the value what you need to be in the [0..length) range.

You're probably right.. now, if only I could train my brain to think of it that way round :)

> More generally, always do the arithmetic with the signed variables in cases like this if there is a possibility of wraparound.

That's good advice, however you have to realise there is a possibility of wraparound, something I didn't do (or I wouldn't have had the problem in the first place) :(

> But if the automatic conversions were specified to do uint->int that would also be fine with me.

But wouldn't that introduce a bug here:
  int a = int.max-1;
  uint b = int.max+1;
  assert(a < b);

wouldn't b be promoted to a signed value of <some negative number>?

> One can also imagine a language with the following inequalities:
>
> +>  unsigned greater-than
> +<  unsigned less than
> ->  signed greater than
> -<  signed less than
> +>= unsigned greater-or-equal
> etc
>
> This would not replace the current >, <, but would essentially just be shorthand for existing expressions:
>
> (A +> B) is the same as (cast(uint)A > cast(uint)B)
>
> .. and so on, except that uint, ulong, ushort, etc would be chosen as needed.
>
> Is this worth doing?  Maybe - it's not a big deal to me, but the signed/unsigned question does represent a common gotcha in certain expressions.

It's a good idea, but, same problem as before; you have to realise length is signed and you have to realise there is a chance for wraparound. A warning about the signed/unsigned comparrison is the very least we should do. I would be tempted to even make it an outright error requiring a cast (or one of these new operators above) to handle.

Regan
April 11, 2006
Regan Heath wrote:
> On Mon, 10 Apr 2006 16:28:00 +0000 (UTC), Kevin Bealer <Kevin_member@pathlink.com> wrote:
>> In article <ops7rncsol23k2f5@nrage.netwin.co.nz>, Regan Heath says...
>>>
>>> Take this code:
>>>
>>> void main()
>>> {
>>>     //..open a file, read line for line, on each line:
>>>
>>>     for(int i = 0; i < line.length-2; i++) {
>>>         if (line[i..i+2] != "||") continue;
>>>         //..etc..
>>>     }
>>> }
>>>
>>>
>>> There is a subtle bug. On all lines with a length of 0 or 1 it will give
>>> the following error:
>>>
>>> Error: ArrayBoundsError line_length.d(6)
>>>
>>>
>>> The problem is of course the statement "i < line.length-2". line.length is
>>> unsigned, and when you - 2 from an unsigned value.. well lets just say
>>> that it's bigger than the actual length of the line - 2.
>>>
>>>
>>> Of course there are plently of other ways to code this, perhaps using
>>> foreach, but that's not the point. The point is that this code  _can_ be
>>> written and on the surface looks fine. Not even -w (warnings) spots the
>>> signed/unsigned problem. At the very least can we get a warning for this?
>>>
>>> Regan
>>
>> I see the "gotcha" here, and whether conversions should be done is an
>> interesting question.  But I wanted to propose a slightly different solution.
>>
>>> for(int i = 0; i+2 < line.length; i++) {
>>
>> Since you are reference "i+2" in the expression, that is really the value what you need to be in the [0..length) range.
> 
> You're probably right.. now, if only I could train my brain to think of it that way round :)
> 
>> More generally, always do the arithmetic with the signed variables in cases like this if there is a possibility of wraparound.
> 
> That's good advice, however you have to realise there is a possibility of wraparound, something I didn't do (or I wouldn't have had the problem in the first place) :(
> 
>> But if the automatic conversions were specified to do uint->int that would also be fine with me.
> 
> But wouldn't that introduce a bug here:
>   int a = int.max-1;
>   uint b = int.max+1;
>   assert(a < b);
> 
> wouldn't b be promoted to a signed value of <some negative number>?
> 
>> One can also imagine a language with the following inequalities:
>>
>> +>  unsigned greater-than
>> +<  unsigned less than
>> ->  signed greater than
>> -<  signed less than
>> +>= unsigned greater-or-equal
>> etc
>>
>> This would not replace the current >, <, but would essentially just be shorthand for existing expressions:
>>
>> (A +> B) is the same as (cast(uint)A > cast(uint)B)
>>
>> .. and so on, except that uint, ulong, ushort, etc would be chosen as needed.
>>
>> Is this worth doing?  Maybe - it's not a big deal to me, but the signed/unsigned question does represent a common gotcha in certain expressions.
> 
> It's a good idea, but, same problem as before; you have to realise length is signed and you have to realise there is a chance for wraparound. A warning about the signed/unsigned comparrison is the very least we should do. I would be tempted to even make it an outright error requiring a cast (or one of these new operators above) to handle.
> 
> Regan

Wouldn't it be somewhat the best, if signed/unsigned comparison actually worked correctly in mathematical sense?

int a;
uint b;

(a<b)  becomes (a<0 || cast(uint)a < b)
(a==b) becomes (a>=0 && cast(uint)a == b)
(a>b)  becomes (a>=0 && cast(uint)a > b)

Unfortunately, that doesn't solve the original problem

if (a < b.length-2)

What would solve it is making .length signed. Even though it should puristically be unsigned, and losing one bit could theoretically be a problem (because you couldn't allocate new byte[more than 2GB], the reality is that a 32-bit app can't allocate more than 2GB of RAM anyway (in Windows at least), and for 64-bit apps, losing that one bit is totally insignificant, unless someone expects a computer with 9 exabytes of ram anytime soon :)

And the only place really needing change (and a trivial one) would be the array resizing code..


xs0
April 11, 2006
In article <e1ftsj$1spp$1@digitaldaemon.com>, xs0 says...
>
>Regan Heath wrote:
>> On Mon, 10 Apr 2006 16:28:00 +0000 (UTC), Kevin Bealer <Kevin_member@pathlink.com> wrote:
>>> In article <ops7rncsol23k2f5@nrage.netwin.co.nz>, Regan Heath says...
>>>>
>>>> Take this code:
>>>>
>>>> void main()
>>>> {
>>>>     //..open a file, read line for line, on each line:
>>>>
>>>>     for(int i = 0; i < line.length-2; i++) {
>>>>         if (line[i..i+2] != "||") continue;
>>>>         //..etc..
>>>>     }
>>>> }
>>>>
>>>>
>>>> There is a subtle bug. On all lines with a length of 0 or 1 it will give the following error:
>>>>
>>>> Error: ArrayBoundsError line_length.d(6)
>>>>
>>>>
>>>> The problem is of course the statement "i < line.length-2".
>>>> line.length is
>>>> unsigned, and when you - 2 from an unsigned value.. well lets just say
>>>> that it's bigger than the actual length of the line - 2.
>>>>
>>>>
>>>> Of course there are plently of other ways to code this, perhaps using foreach, but that's not the point. The point is that this code  _can_ be written and on the surface looks fine. Not even -w (warnings) spots the signed/unsigned problem. At the very least can we get a warning for this?
>>>>
>>>> Regan
>>>
>>> I see the "gotcha" here, and whether conversions should be done is an interesting question.  But I wanted to propose a slightly different solution.
>>>
>>>> for(int i = 0; i+2 < line.length; i++) {
>>>
>>> Since you are reference "i+2" in the expression, that is really the value what you need to be in the [0..length) range.
>> 
>> You're probably right.. now, if only I could train my brain to think of it that way round :)
>> 
>>> More generally, always do the arithmetic with the signed variables in cases like this if there is a possibility of wraparound.
>> 
>> That's good advice, however you have to realise there is a possibility of wraparound, something I didn't do (or I wouldn't have had the problem in the first place) :(
>> 
>>> But if the automatic conversions were specified to do uint->int that would also be fine with me.
>> 
>> But wouldn't that introduce a bug here:
>>   int a = int.max-1;
>>   uint b = int.max+1;
>>   assert(a < b);
>> 
>> wouldn't b be promoted to a signed value of <some negative number>?

True, hadn't thought of that.  I guess the correct thing (mathematically) is
what is proposed by xs0 below (however, see comments).

>>> One can also imagine a language with the following inequalities:
>>>
>>> +>  unsigned greater-than
>>> +<  unsigned less than
>>> ->  signed greater than
>>> -<  signed less than
>>> +>= unsigned greater-or-equal
>>> etc
>>>
>>> This would not replace the current >, <, but would essentially just be shorthand for existing expressions:
>>>
>>> (A +> B) is the same as (cast(uint)A > cast(uint)B)
>>>
>>> .. and so on, except that uint, ulong, ushort, etc would be chosen as needed.
>>>
>>> Is this worth doing?  Maybe - it's not a big deal to me, but the signed/unsigned question does represent a common gotcha in certain expressions.
>> 
>> It's a good idea, but, same problem as before; you have to realise length is signed and you have to realise there is a chance for wraparound. A warning about the signed/unsigned comparrison is the very least we should do. I would be tempted to even make it an outright error requiring a cast (or one of these new operators above) to handle.
>> 
>> Regan
>
>Wouldn't it be somewhat the best, if signed/unsigned comparison actually worked correctly in mathematical sense?
>
>int a;
>uint b;
>
>(a<b)  becomes (a<0 || cast(uint)a < b)
>(a==b) becomes (a>=0 && cast(uint)a == b)
>(a>b)  becomes (a>=0 && cast(uint)a > b)

I like this conceptually - it seems like definitely the correct approach for a language like python, but it has the unfortunate effect of adding a conditional to what is otherwise a one-instruction subtraction (< is a subtract in asm).

>Unfortunately, that doesn't solve the original problem
>
>if (a < b.length-2)
>
>What would solve it is making .length signed. Even though it should puristically be unsigned, and losing one bit could theoretically be a problem (because you couldn't allocate new byte[more than 2GB], the reality is that a 32-bit app can't allocate more than 2GB of RAM anyway (in Windows at least), and for 64-bit apps, losing that one bit is totally insignificant, unless someone expects a computer with 9 exabytes of ram anytime soon :)
>
>And the only place really needing change (and a trivial one) would be the array resizing code..
>
>
>xs0

The unsigned .length would fix this particular issue.  But I think this might be one of those things where every solution seems to cause problems in some other area.  For instance, in C, char is (usually) signed, which is good for small numbers, but when you use char as an array index, it walks off the front of the array for anything over 128.  Lots and lots of C programs have bugs from this. It's actually up to the compiler writer whether char is signed in C...

As a result, when writing crypto and hash function code in C, people usually have to cast the types to get reliable output.  Such code is often peppered by casts, to force size and signedness to the right kind.  Sometimes you see code where about half of these are completely unnecessary, but the author simply decided that *Let's never have to fix this thing again* and did a cast for every math operation.

I realize this is all tangential, but I think that there are three or four ways to handle this and all of them probably have a few "gotchas".  You'd almost have to write a big program with the signed version of .length to know if you got bit somehow.

I checked a hunch - it looks like .length was changed to size_t in dmd 0.77. It's also mentioned in the portability section of the documentation:

"The .length, .size, .sizeof, and .alignof  properties will be of type size_t."

Not sure what it was before .77.

Kevin


April 11, 2006
Kevin Bealer wrote:
> In article <e1ftsj$1spp$1@digitaldaemon.com>, xs0 says...
> 
>>Regan Heath wrote:
>>
>>>On Mon, 10 Apr 2006 16:28:00 +0000 (UTC), Kevin Bealer <Kevin_member@pathlink.com> wrote:
>>>
>>>>In article <ops7rncsol23k2f5@nrage.netwin.co.nz>, Regan Heath says...
>>>>
>>>>>Take this code:
>>>>>
>>>>>void main()
>>>>>{
>>>>>    //..open a file, read line for line, on each line:
>>>>>
>>>>>    for(int i = 0; i < line.length-2; i++) {
>>>>>        if (line[i..i+2] != "||") continue;
>>>>>        //..etc..
>>>>>    }
>>>>>}
>>>>>
>>>>>
>>>>>There is a subtle bug. On all lines with a length of 0 or 1 it will give
>>>>>the following error:
>>>>>
>>>>>Error: ArrayBoundsError line_length.d(6)
>>>>>
>>>>>
>>>>>The problem is of course the statement "i < line.length-2". line.length is
>>>>>unsigned, and when you - 2 from an unsigned value.. well lets just say
>>>>>that it's bigger than the actual length of the line - 2.
>>>>>
>>>>>
>>>>>Of course there are plently of other ways to code this, perhaps using
>>>>>foreach, but that's not the point. The point is that this code  _can_ be
>>>>>written and on the surface looks fine. Not even -w (warnings) spots the
>>>>>signed/unsigned problem. At the very least can we get a warning for this?
>>>>>
>>>>>Regan
>>>>
>>>>I see the "gotcha" here, and whether conversions should be done is an
>>>>interesting question.  But I wanted to propose a slightly different solution.
>>>>
>>>>
>>>>>for(int i = 0; i+2 < line.length; i++) {
>>>>
>>>>Since you are reference "i+2" in the expression, that is really the value what you need to be in the [0..length) range.
>>>
>>>You're probably right.. now, if only I could train my brain to think of it that way round :)
>>>
>>>
>>>>More generally, always do the arithmetic with the signed variables in cases like this if there is a possibility of wraparound.
>>>
>>>That's good advice, however you have to realise there is a possibility of wraparound, something I didn't do (or I wouldn't have had the problem in the first place) :(
>>>
>>>
>>>>But if the automatic conversions were specified to do uint->int that would also be fine with me.
>>>
>>>But wouldn't that introduce a bug here:
>>>  int a = int.max-1;
>>>  uint b = int.max+1;
>>>  assert(a < b);
>>>
>>>wouldn't b be promoted to a signed value of <some negative number>?
> 
> 
> True, hadn't thought of that.  I guess the correct thing (mathematically) is
> what is proposed by xs0 below (however, see comments).
> 
> 
>>>>One can also imagine a language with the following inequalities:
>>>>
>>>>+>  unsigned greater-than
>>>>+<  unsigned less than
>>>>->  signed greater than
>>>>-<  signed less than
>>>>+>= unsigned greater-or-equal
>>>>etc
>>>>
>>>>This would not replace the current >, <, but would essentially just be shorthand for existing expressions:
>>>>
>>>>(A +> B) is the same as (cast(uint)A > cast(uint)B)
>>>>
>>>>.. and so on, except that uint, ulong, ushort, etc would be chosen as needed.
>>>>
>>>>Is this worth doing?  Maybe - it's not a big deal to me, but the signed/unsigned question does represent a common gotcha in certain expressions.
>>>
>>>It's a good idea, but, same problem as before; you have to realise length is signed and you have to realise there is a chance for wraparound. A warning about the signed/unsigned comparrison is the very least we should do. I would be tempted to even make it an outright error requiring a cast (or one of these new operators above) to handle.
>>>
>>>Regan
>>
>>Wouldn't it be somewhat the best, if signed/unsigned comparison actually worked correctly in mathematical sense?
>>
>>int a;
>>uint b;
>>
>>(a<b)  becomes (a<0 || cast(uint)a < b)
>>(a==b) becomes (a>=0 && cast(uint)a == b)
>>(a>b)  becomes (a>=0 && cast(uint)a > b)
> 
> 
> I like this conceptually - it seems like definitely the correct approach for a
> language like python, but it has the unfortunate effect of adding a conditional
> to what is otherwise a one-instruction subtraction (< is a subtract in asm).
> 
> 
>>Unfortunately, that doesn't solve the original problem
>>
>>if (a < b.length-2)
>>
>>What would solve it is making .length signed. Even though it should puristically be unsigned, and losing one bit could theoretically be a problem (because you couldn't allocate new byte[more than 2GB], the reality is that a 32-bit app can't allocate more than 2GB of RAM anyway (in Windows at least), and for 64-bit apps, losing that one bit is totally insignificant, unless someone expects a computer with 9 exabytes of ram anytime soon :)
>>
>>And the only place really needing change (and a trivial one) would be the array resizing code..
>>
>>
>>xs0
> 
> 
> The unsigned .length would fix this particular issue.  But I think
> this might be one of those things where every solution seems to cause
> problems in some other area.
> 
> I realize this is all tangential, but I think that there are three or
> four ways to handle this and all of them probably have a few
> "gotchas".  You'd almost have to write a big program with the signed
> version of .length to know if you got bit somehow.

I agree.

This is not my official opinion, but I sometimes feel like the guy who invented Cruise Control, and this customer comes back and complains that what's the use, he still has to use the steering wheel.
1 2
Next ›   Last »