www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - A little puzzle

reply bearophile <bearophileHUGS lycos.com> writes:
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
Sep 19 2011
next sibling parent reply "Simen Kjaeraas" <simen.kjaras gmail.com> writes:
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
Sep 19 2011
parent reply Adam Burton <adz21c gmail.com> writes:
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?

ElementType of Range1 not matching Range2 ElementType. Could this be due to using 64bit (size_t is ulong)?
Sep 19 2011
parent Timon Gehr <timon.gehr gmx.ch> writes:
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?

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.
Sep 19 2011
prev sibling next sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
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); }
Sep 19 2011
prev sibling parent "Regan Heath" <regan netmail.co.nz> writes:
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/
Sep 20 2011