Thread overview
A little puzzle
Sep 19, 2011
bearophile
Sep 19, 2011
Simen Kjaeraas
Sep 19, 2011
Adam Burton
Sep 19, 2011
Timon Gehr
Sep 20, 2011
Regan Heath
Sep 19, 2011
Timon Gehr
September 19, 2011
A tiny puzzle I've shown on IRC. This is supposed to create an inverted array of cards, but what does it print instead?

import std.stdio, std.algorithm, std.range;
void main() {
    int[52] cards;
    copy(iota(cards.length - 1, -1, -1), cards[]);
    writeln(cards);
}

Bye,
bearophile
September 19, 2011
On Mon, 19 Sep 2011 23:20:47 +0200, bearophile <bearophileHUGS@lycos.com> wrote:

> A tiny puzzle I've shown on IRC. This is supposed to create an inverted array of cards, but what does it print instead?
>
> import std.stdio, std.algorithm, std.range;
> void main() {
>     int[52] cards;
>     copy(iota(cards.length - 1, -1, -1), cards[]);
>     writeln(cards);
> }

Gawds, that's an ugly bug. For those who can't spot it,
typeof(cards.length) == uint, hence -1 is converted to a uint
(4_294_967_295, to be exact). iota then says 'that's fine, I'll just
return an empty range for you.'
Solution: knock some sense into integral promotion rules.
Workaround: cast(int)cards.length.

What was the rationale for having unsigned array lengths, again?

-- 
  Simen
September 19, 2011
On 09/19/2011 11:20 PM, bearophile wrote:
> A tiny puzzle I've shown on IRC. This is supposed to create an inverted array of cards, but what does it print instead?
>
> import std.stdio, std.algorithm, std.range;
> void main() {
>      int[52] cards;
>      copy(iota(cards.length - 1, -1, -1), cards[]);
>      writeln(cards);
> }
>
> Bye,
> bearophile

The same as this code, of course!

import std.stdio, std.algorithm, std.range;
void main() {
        int[52] cards;
        for(auto i=cards.length-1,v=0; i>-1; i--, v++) cards[i]=v;
        writeln(cards);
}

September 19, 2011
Simen Kjaeraas wrote:

> On Mon, 19 Sep 2011 23:20:47 +0200, bearophile <bearophileHUGS@lycos.com> wrote:
> 
>> A tiny puzzle I've shown on IRC. This is supposed to create an inverted array of cards, but what does it print instead?
>>
>> import std.stdio, std.algorithm, std.range;
>> void main() {
>>     int[52] cards;
>>     copy(iota(cards.length - 1, -1, -1), cards[]);
>>     writeln(cards);
>> }
> 
> Gawds, that's an ugly bug. For those who can't spot it,
> typeof(cards.length) == uint, hence -1 is converted to a uint
> (4_294_967_295, to be exact). iota then says 'that's fine, I'll just
> return an empty range for you.'
> Solution: knock some sense into integral promotion rules.
> Workaround: cast(int)cards.length.
> 
> What was the rationale for having unsigned array lengths, again?
> 
That's not what happened for me. It failed to compile for me due to ElementType of Range1 not matching Range2 ElementType. Could this be due to using 64bit (size_t is ulong)?
September 19, 2011
On 09/20/2011 12:50 AM, Adam Burton wrote:
> Simen Kjaeraas wrote:
>
>> On Mon, 19 Sep 2011 23:20:47 +0200, bearophile<bearophileHUGS@lycos.com>
>> wrote:
>>
>>> A tiny puzzle I've shown on IRC. This is supposed to create an inverted
>>> array of cards, but what does it print instead?
>>>
>>> import std.stdio, std.algorithm, std.range;
>>> void main() {
>>>      int[52] cards;
>>>      copy(iota(cards.length - 1, -1, -1), cards[]);
>>>      writeln(cards);
>>> }
>>
>> Gawds, that's an ugly bug. For those who can't spot it,
>> typeof(cards.length) == uint, hence -1 is converted to a uint
>> (4_294_967_295, to be exact). iota then says 'that's fine, I'll just
>> return an empty range for you.'
>> Solution: knock some sense into integral promotion rules.
>> Workaround: cast(int)cards.length.
>>
>> What was the rationale for having unsigned array lengths, again?
>>
> That's not what happened for me. It failed to compile for me due to
> ElementType of Range1 not matching Range2 ElementType. Could this be due to
> using 64bit (size_t is ulong)?

If you recompile with the -m32 switch it should be accepted.


September 20, 2011
On Mon, 19 Sep 2011 23:09:45 +0100, Simen Kjaeraas <simen.kjaras@gmail.com> wrote:

> On Mon, 19 Sep 2011 23:20:47 +0200, bearophile <bearophileHUGS@lycos.com> wrote:
>
>> A tiny puzzle I've shown on IRC. This is supposed to create an inverted array of cards, but what does it print instead?
>>
>> import std.stdio, std.algorithm, std.range;
>> void main() {
>>     int[52] cards;
>>     copy(iota(cards.length - 1, -1, -1), cards[]);
>>     writeln(cards);
>> }
>
> Gawds, that's an ugly bug. For those who can't spot it,
> typeof(cards.length) == uint, hence -1 is converted to a uint
> (4_294_967_295, to be exact). iota then says 'that's fine, I'll just
> return an empty range for you.'
> Solution: knock some sense into integral promotion rules.
> Workaround: cast(int)cards.length.
>
> What was the rationale for having unsigned array lengths, again?

Well.. logically it makes sense as arrays cannot have negative lengths, but practically, this bug is what happens as a result.  This is the reason I typically use signed int for lengths, unless I expect the length to exceed max signed int.  It's also a good idea if you ever do any subtraction/calculation with them, as you don't want to underflow to max signed int ever.  It means that in my daily work I have to cast the return value of strlen() everywhere (cos my compiler complains, but only in 64 bit mode..).. I mean, really, when are you going to have a string which is longer than max signed int?!  It's just nonsensical.

-- 
Using Opera's revolutionary email client: http://www.opera.com/mail/