www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Array initialization quiz

reply bearophile <bearophileHUGS lycos.com> writes:
A little D2 quiz, of course. This was discussed some time ago, but repeating
now and then such things doesn't hurt in D.learn.

Do you think this little program compiles? Or do you think the D2 compiler will
refuse to compile it and ask you for a cast from int -> ubyte?

If this compiles (maybe because you have added a cast at line 4) do you think
this program is working correctly?


void main() {
    ubyte[256] table;
    foreach (ubyte i, ref x; table)
        x = 255 - i;
}

Bye,
bearophile
Nov 28 2011
next sibling parent reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
I get an infinite loop. :s
Nov 28 2011
parent reply bearophile <bearophileHUGS lycos.com> writes:
Andrej Mitrovic:

 I get an infinite loop. :s

In your brain, really? Is that dangerous? Bye, bearophile
Nov 28 2011
parent reply bearophile <bearophileHUGS lycos.com> writes:
Andrej Mitrovic:

 Err no? Running after compilation goes into an infinite loop on 2.056.

Silly, this is a quiz, you need to try to answer without compiling it first :-) Do you know why the compiler doesn't ask you for a cast, and why the run does that? Bye, bearophile
Nov 28 2011
parent reply deadalnix <deadalnix gmail.com> writes:
Le 29/11/2011 04:11, Andrej Mitrovic a écrit :
 On 11/29/11, bearophile<bearophileHUGS lycos.com>  wrote:
 Do you know why the compiler doesn't ask you for a cast, and why the run
 does that?

Because foreach is broken? http://d.puremagic.com/issues/show_bug.cgi?id=4510

No it has nothing to do with this bug. But actually, this exemple should generate a warning at least, or being illegal eventually. I being ubyte, the max value is 255, so you always ends up with a valid value of i and the loop never stop.
Nov 29 2011
parent bearophile <bearophileHUGS lycos.com> writes:
deadalnix:

 No it has nothing to do with this bug.

I tend to agree.
 But actually, this exemple should 
 generate a warning at least, or being illegal eventually.

I'd like that code to loop on all array 256 items once, and then stop :-) Bye, bearophile
Nov 29 2011
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
Err no? Running after compilation goes into an infinite loop on 2.056.
Nov 28 2011
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 11/29/11, bearophile <bearophileHUGS lycos.com> wrote:
 Do you know why the compiler doesn't ask you for a cast, and why the run
 does that?

Because foreach is broken? http://d.puremagic.com/issues/show_bug.cgi?id=4510
Nov 28 2011
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
I meant that in a sarcastic way. :)
Nov 29 2011
prev sibling next sibling parent reply "Marco Leise" <Marco.Leise gmx.de> writes:
Am 29.11.2011, 14:53 Uhr, schrieb bearophile <bearophileHUGS lycos.com>:

 deadalnix:

 No it has nothing to do with this bug.

I tend to agree.
 But actually, this exemple should
 generate a warning at least, or being illegal eventually.

I'd like that code to loop on all array 256 items once, and then stop :-) Bye, bearophile

Is it evil if I propose that 'i' should always be size_t and nothing else?
Nov 29 2011
parent reply Xinok <xinok live.com> writes:
On 11/30/2011 7:50 AM, Steven Schveighoffer wrote:
 On Tue, 29 Nov 2011 15:06:11 -0500, Jonathan M Davis
 <jmdavisProg gmx.com> wrote:

 The type of the index should be irrelavent to the underlying loop
 mechanism.

 Note that the issue is really that foreach(T i, val; arr) {...}
 translates to for(T i = 0; i < arr.length; ++i) {auto val = arr[i]; ...}

 Why can't it be (aside from the limitation in for-loop syntax, but you
 get the idea): for(size_t _i = 0, T i = _i; _i < arr.length; i = ++_i)
 {auto val = arr[_i]; ...}

 Same issue with foreach(i; -10..10), what if I wanted to do foreach
 (ubyte i; ubyte.min..ubyte.max + 1). This should not result in an
 infinite loop, I should be able to use foreach to iterate all the values
 of ubyte. The compiler should just "figure out" how to do it right.

 -Steve

This actually doesn't compile: foreach (ubyte i; ubyte.min..ubyte.max + 1) Error: cannot implicitly convert expression (256) of type int to ubyte It's a little more to type, but just write a property which does an explicit cast: foreach(_i; ubyte.min .. ubyte.max + 1){ ubyte i(){ return cast(ubyte)_i; } }
Nov 30 2011
parent reply Xinok <xinok live.com> writes:
On 11/30/2011 11:46 AM, Steven Schveighoffer wrote:
 On Wed, 30 Nov 2011 10:54:11 -0500, Xinok <xinok live.com> wrote:

 On 11/30/2011 7:50 AM, Steven Schveighoffer wrote:
 On Tue, 29 Nov 2011 15:06:11 -0500, Jonathan M Davis
 <jmdavisProg gmx.com> wrote:

 The type of the index should be irrelavent to the underlying loop
 mechanism.

 Note that the issue is really that foreach(T i, val; arr) {...}
 translates to for(T i = 0; i < arr.length; ++i) {auto val = arr[i]; ...}

 Why can't it be (aside from the limitation in for-loop syntax, but you
 get the idea): for(size_t _i = 0, T i = _i; _i < arr.length; i = ++_i)
 {auto val = arr[_i]; ...}

 Same issue with foreach(i; -10..10), what if I wanted to do foreach
 (ubyte i; ubyte.min..ubyte.max + 1). This should not result in an
 infinite loop, I should be able to use foreach to iterate all the values
 of ubyte. The compiler should just "figure out" how to do it right.

 -Steve

This actually doesn't compile: foreach (ubyte i; ubyte.min..ubyte.max + 1) Error: cannot implicitly convert expression (256) of type int to ubyte It's a little more to type, but just write a property which does an explicit cast: foreach(_i; ubyte.min .. ubyte.max + 1){ ubyte i(){ return cast(ubyte)_i; } }

This is hugely inefficient... foreach(_i; ubyte.min..ubyte.max + 1){ ubyte i = cast(ubyte)_i; } But my point was, foreach over a range gives me all the elements in a range, regardless of how the underlying loop is constructed. The limitation by the compiler is artificial. I remember at one point there was someone who had actual code that resulted in a loop for ubytes, or was trying to figure out how to foreach over all possible ubyte values. -Steve

It shouldn't be. The compiler should be smart enough to inline the function and optimize the typecast to something like this: void main(string[] args){ foreach(_i; ubyte.min .. ubyte.max + 1) writeln(*cast(ubyte*)&_i); } This would actually be faster since you don't have to iterate two variables.
Nov 30 2011
parent =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 11/30/2011 10:17 AM, Xinok wrote:
 On 11/30/2011 11:46 AM, Steven Schveighoffer wrote:
 foreach(_i; ubyte.min..ubyte.max + 1){
 ubyte i = cast(ubyte)_i;
 }

 But my point was, foreach over a range gives me all the elements in a
 range, regardless of how the underlying loop is constructed. The
 limitation by the compiler is artificial.

 I remember at one point there was someone who had actual code that
 resulted in a loop for ubytes, or was trying to figure out how to
 foreach over all possible ubyte values.

 -Steve

It shouldn't be. The compiler should be smart enough to inline the function and optimize the typecast to something like this: void main(string[] args){ foreach(_i; ubyte.min .. ubyte.max + 1) writeln(*cast(ubyte*)&_i); } This would actually be faster since you don't have to iterate two variables.

But variables may be implemented on CPU registers and be fast. That is easy to do with Steven's code and cast above. In your code, taking the address of _i would put _i in memory. (Unless the compiler has an optimization for that. Too lazy to check. :() Also, *cast(ubyte*)&_i works only on little endian systems, right? But you meant that the compiler should take care of endianness as well. Ali
Nov 30 2011
prev sibling next sibling parent "Marco Leise" <Marco.Leise gmx.de> writes:
Am 29.11.2011, 20:41 Uhr, schrieb Marco Leise <Marco.Leise gmx.de>:

 Am 29.11.2011, 14:53 Uhr, schrieb bearophile <bearophileHUGS lycos.com>:

 deadalnix:

 No it has nothing to do with this bug.

I tend to agree.
 But actually, this exemple should
 generate a warning at least, or being illegal eventually.

I'd like that code to loop on all array 256 items once, and then stop :-) Bye, bearophile

Is it evil if I propose that 'i' should always be size_t and nothing else?

Yes, because you can iterate over -10..10 as well -.-
Nov 29 2011
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Tuesday, November 29, 2011 20:42:59 Marco Leise wrote:
 Am 29.11.2011, 20:41 Uhr, schrieb Marco Leise <Marco.Leise gmx.de>:
 Am 29.11.2011, 14:53 Uhr, schrieb bearophile <bearophileHUGS lycos.com>:
 deadalnix:
 No it has nothing to do with this bug.

I tend to agree.
 But actually, this exemple should
 generate a warning at least, or being illegal eventually.

I'd like that code to loop on all array 256 items once, and then stop :-) Bye, bearophile

Is it evil if I propose that 'i' should always be size_t and nothing else?

Yes, because you can iterate over -10..10 as well -.-

I would argue that i should always be size_t if it's an index. So, foreach(i; -10 .. 10) {} would be valid, but int[] arr; foreach(byte i, val; arr) {} wouldn't be. - Jonathn M Davis
Nov 29 2011
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Tue, 29 Nov 2011 15:06:11 -0500, Jonathan M Davis <jmdavisProg gmx.com>  
wrote:

 On Tuesday, November 29, 2011 20:42:59 Marco Leise wrote:
 Am 29.11.2011, 20:41 Uhr, schrieb Marco Leise <Marco.Leise gmx.de>:
 Am 29.11.2011, 14:53 Uhr, schrieb bearophile  

 deadalnix:
 No it has nothing to do with this bug.

I tend to agree.
 But actually, this exemple should
 generate a warning at least, or being illegal eventually.

I'd like that code to loop on all array 256 items once, and then stop :-) Bye, bearophile

Is it evil if I propose that 'i' should always be size_t and nothing else?

Yes, because you can iterate over -10..10 as well -.-

I would argue that i should always be size_t if it's an index. So, foreach(i; -10 .. 10) {} would be valid, but int[] arr; foreach(byte i, val; arr) {} wouldn't be.

The type of the index should be irrelavent to the underlying loop mechanism. Note that the issue is really that foreach(T i, val; arr) {...} translates to for(T i = 0; i < arr.length; ++i) {auto val = arr[i]; ...} Why can't it be (aside from the limitation in for-loop syntax, but you get the idea): for(size_t _i = 0, T i = _i; _i < arr.length; i = ++_i) {auto val = arr[_i]; ...} Same issue with foreach(i; -10..10), what if I wanted to do foreach (ubyte i; ubyte.min..ubyte.max + 1). This should not result in an infinite loop, I should be able to use foreach to iterate all the values of ubyte. The compiler should just "figure out" how to do it right. -Steve
Nov 30 2011
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Wed, 30 Nov 2011 10:54:11 -0500, Xinok <xinok live.com> wrote:

 On 11/30/2011 7:50 AM, Steven Schveighoffer wrote:
 On Tue, 29 Nov 2011 15:06:11 -0500, Jonathan M Davis
 <jmdavisProg gmx.com> wrote:

 The type of the index should be irrelavent to the underlying loop
 mechanism.

 Note that the issue is really that foreach(T i, val; arr) {...}
 translates to for(T i = 0; i < arr.length; ++i) {auto val = arr[i]; ...}

 Why can't it be (aside from the limitation in for-loop syntax, but you
 get the idea): for(size_t _i = 0, T i = _i; _i < arr.length; i = ++_i)
 {auto val = arr[_i]; ...}

 Same issue with foreach(i; -10..10), what if I wanted to do foreach
 (ubyte i; ubyte.min..ubyte.max + 1). This should not result in an
 infinite loop, I should be able to use foreach to iterate all the values
 of ubyte. The compiler should just "figure out" how to do it right.

 -Steve

This actually doesn't compile: foreach (ubyte i; ubyte.min..ubyte.max + 1) Error: cannot implicitly convert expression (256) of type int to ubyte It's a little more to type, but just write a property which does an explicit cast: foreach(_i; ubyte.min .. ubyte.max + 1){ ubyte i(){ return cast(ubyte)_i; } }

This is hugely inefficient... foreach(_i; ubyte.min..ubyte.max + 1){ ubyte i = cast(ubyte)_i; } But my point was, foreach over a range gives me all the elements in a range, regardless of how the underlying loop is constructed. The limitation by the compiler is artificial. I remember at one point there was someone who had actual code that resulted in a loop for ubytes, or was trying to figure out how to foreach over all possible ubyte values. -Steve
Nov 30 2011
prev sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 11/30/11, Steven Schveighoffer <schveiguy yahoo.com> wrote:
 I remember at one point there was someone who had actual code that
 resulted in a loop for ubytes, or was trying to figure out how to foreach
 over all possible ubyte values.

Instant flashback, I think it was this: http://www.digitalmars.com/d/archives/digitalmars/D/learn/Foreach_with_byte_problems_24997.html :)
Nov 30 2011