digitalmars.D - casting array literals doesn't work as stated in the docs
- Trass3r (17/17) Jan 02 2010 http://www.digitalmars.com/d/2.0/expression.html#ArrayLiteral
- Denis Koroskin (7/24) Jan 02 2010 Yes and no. It used to work (and should still work), but the behavior wa...
- Steven Schveighoffer (12/47) Jan 02 2010 the cast-entire-array takes care of that. Corrected docs example:
- Denis Koroskin (8/60) Jan 02 2010 Array casting is something I avoid as a plague. It is highly inconsisten...
- Steven Schveighoffer (12/19) Jan 02 2010 It's very consistent. It never does a per-element copy at runtime.
- Trass3r (2/5) Jan 03 2010 Second one still doesn't work at compile-time.
- bearophile (4/9) Jan 03 2010 It's not supposed to work, "dup" allocated memory with malloc, so it's (...
- Trass3r (9/11) Jan 03 2010 So how to "create" an array expression at compile-time to enforce
- bearophile (5/9) Jan 03 2010 What's wrong with just (D2 code):
- Trass3r (11/14) Jan 03 2010 Nothing, but it's just the stripped down example.
- bearophile (43/50) Jan 03 2010 That's the correct thing. Ints are the default because D2 doesn't defaul...
- Trass3r (14/19) Jan 03 2010 Alternative 1: I heard struct literals could be removed.
- bearophile (7/12) Jan 03 2010 But it's clean & readable, and more flexible because later you can add a...
- Trass3r (7/16) Jan 03 2010 I don't need to be flexible. In this simple case I only need a
- Steven Schveighoffer (9/26) Jan 03 2010 You should be able to do this I would think:
http://www.digitalmars.com/d/2.0/expression.html#ArrayLiteral The code example from the docs yields [1 1] and [1 0 1 0] instead of [1 1] and [257] for dmd 2.037. Additionally short[] t = [cast(short) 5, 3]; short[] t2 = [cast(short) 5, 3].dup; void main() { ... yields: Error: cannot evaluate _adDupT((& D12TypeInfo_G2i6__initZ),[5,3]) at compile-time Error: cannot implicitly convert expression (_adDupT((& D12TypeInfo_G2i6__initZ),[5,3])) of type int[] to short[] Error: cannot evaluate _adDupT((& D12TypeInfo_G2i6__initZ),[5,3]) at compile-time Using int instead of short only removes the second message. Compiler bug(s)?
Jan 02 2010
On Sun, 03 Jan 2010 04:23:00 +0300, Trass3r <mrmocool gmx.de> wrote:http://www.digitalmars.com/d/2.0/expression.html#ArrayLiteral The code example from the docs yields [1 1] and [1 0 1 0] instead of [1 1] and [257] for dmd 2.037. Additionally short[] t = [cast(short) 5, 3]; short[] t2 = [cast(short) 5, 3].dup; void main() { ... yields: Error: cannot evaluate _adDupT((& D12TypeInfo_G2i6__initZ),[5,3]) at compile-time Error: cannot implicitly convert expression (_adDupT((& D12TypeInfo_G2i6__initZ),[5,3])) of type int[] to short[] Error: cannot evaluate _adDupT((& D12TypeInfo_G2i6__initZ),[5,3]) at compile-time Using int instead of short only removes the second message. Compiler bug(s)?Yes and no. It used to work (and should still work), but the behavior was changed to take all array literal values into consideration. "Proper" code should look like this: short[] t = [cast(short) 5, cast(short)3]; which is err... I'll let someone else to decide. Just imagine there are ten (or more) values in an array literal.
Jan 02 2010
On Sat, 02 Jan 2010 20:54:30 -0500, Denis Koroskin <2korden gmail.com> wrote:On Sun, 03 Jan 2010 04:23:00 +0300, Trass3r <mrmocool gmx.de> wrote:the cast-entire-array takes care of that. Corrected docs example: short[] rt = cast(short[]) (cast(byte[])[1, 1]).dup; Note the cast of the entire literal, not just the first element. so now, if you want to set the type of the array, cast the entire array. If you want to set the type of only one element, cast that one element, but the runtime might decide to use a bigger type anyways. correcting your code: short[] t = cast(short[])[5,3]; short[] t2 = cast(short[])[5,3].dup; -Stevehttp://www.digitalmars.com/d/2.0/expression.html#ArrayLiteral The code example from the docs yields [1 1] and [1 0 1 0] instead of [1 1] and [257] for dmd 2.037. Additionally short[] t = [cast(short) 5, 3]; short[] t2 = [cast(short) 5, 3].dup; void main() { ... yields: Error: cannot evaluate _adDupT((& D12TypeInfo_G2i6__initZ),[5,3]) at compile-time Error: cannot implicitly convert expression (_adDupT((& D12TypeInfo_G2i6__initZ),[5,3])) of type int[] to short[] Error: cannot evaluate _adDupT((& D12TypeInfo_G2i6__initZ),[5,3]) at compile-time Using int instead of short only removes the second message. Compiler bug(s)?Yes and no. It used to work (and should still work), but the behavior was changed to take all array literal values into consideration. "Proper" code should look like this: short[] t = [cast(short) 5, cast(short)3]; which is err... I'll let someone else to decide. Just imagine there are ten (or more) values in an array literal.
Jan 02 2010
On Sun, 03 Jan 2010 05:56:21 +0300, Steven Schveighoffer <schveiguy yahoo.com> wrote:On Sat, 02 Jan 2010 20:54:30 -0500, Denis Koroskin <2korden gmail.com> wrote:Array casting is something I avoid as a plague. It is highly inconsistent: in some cases, it does bitwise casting (kind of a reinterpret_cast, changing size of an array), in others - in creates per-element copy of an array, thus doing at runtime something I'd like to be done at compile-time. Maybe it's just me, but I wouldn't recommend anyone using array casting (other that T[] -> void[]).On Sun, 03 Jan 2010 04:23:00 +0300, Trass3r <mrmocool gmx.de> wrote:the cast-entire-array takes care of that. Corrected docs example: short[] rt = cast(short[]) (cast(byte[])[1, 1]).dup; Note the cast of the entire literal, not just the first element. so now, if you want to set the type of the array, cast the entire array. If you want to set the type of only one element, cast that one element, but the runtime might decide to use a bigger type anyways. correcting your code: short[] t = cast(short[])[5,3]; short[] t2 = cast(short[])[5,3].dup; -Stevehttp://www.digitalmars.com/d/2.0/expression.html#ArrayLiteral The code example from the docs yields [1 1] and [1 0 1 0] instead of [1 1] and [257] for dmd 2.037. Additionally short[] t = [cast(short) 5, 3]; short[] t2 = [cast(short) 5, 3].dup; void main() { ... yields: Error: cannot evaluate _adDupT((& D12TypeInfo_G2i6__initZ),[5,3]) at compile-time Error: cannot implicitly convert expression (_adDupT((& D12TypeInfo_G2i6__initZ),[5,3])) of type int[] to short[] Error: cannot evaluate _adDupT((& D12TypeInfo_G2i6__initZ),[5,3]) at compile-time Using int instead of short only removes the second message. Compiler bug(s)?Yes and no. It used to work (and should still work), but the behavior was changed to take all array literal values into consideration. "Proper" code should look like this: short[] t = [cast(short) 5, cast(short)3]; which is err... I'll let someone else to decide. Just imagine there are ten (or more) values in an array literal.
Jan 02 2010
On Sat, 02 Jan 2010 22:41:05 -0500, Denis Koroskin <2korden gmail.com> wrote:Array casting is something I avoid as a plague. It is highly inconsistent: in some cases, it does bitwise casting (kind of a reinterpret_cast, changing size of an array), in others - in creates per-element copy of an array, thus doing at runtime something I'd like to be done at compile-time. Maybe it's just me, but I wouldn't recommend anyone using array casting (other that T[] -> void[]).It's very consistent. It never does a per-element copy at runtime. Essentially, doing this: cast(byte[])[a, b, c] is equivalent to doing this: [cast(byte)a, cast(byte)b, cast(byte)c] the rules are: if you cast an array literal, then it reinterprets each element as if each element were cast to that type. otherwise, it's a reinterpret_cast as you say. -Steve
Jan 02 2010
Steven Schveighoffer schrieb:if you cast an array literal, then it reinterprets each element as if each element were cast to that type. otherwise, it's a reinterpret_cast as you say.Any reason for defining the behavior like that? The problem is forcing the compiler to reinterpret_cast at compile-time. Using .dup like in the docs doesn't work: http://codepad.org/P9EZ0dIB without using the ugly auto PALETTE = (cast(RGBA*) cast(ubyte[]) [0xFF,...]) [0 .. 256];
Jan 03 2010
Trass3r schrieb:Any reason for defining the behavior like that?I mean converting an array to an array of structs doesn't make sense as soon as you have multiple struct members cause cast(Foo[])[0,1,2,3,4] gets rewritten as [cast(Foo) 0, cast(Foo) 1, cast(Foo) 2, cast(Foo) 3, cast(Foo) 4] which becomes [Foo(0), Foo(1), Foo(2), Foo(3), Foo(4)] if I didn't miss anything.
Jan 03 2010
Steven Schveighoffer schrieb:short[] t = cast(short[])[5,3]; short[] t2 = cast(short[])[5,3].dup;Second one still doesn't work at compile-time.
Jan 03 2010
Trass3r:It's not supposed to work, "dup" allocated memory with malloc, so it's (currently) a run time thing (in future this may change). Bye, bearophileshort[] t = cast(short[])[5,3]; short[] t2 = cast(short[])[5,3].dup;Second one still doesn't work at compile-time.
Jan 03 2010
Am 03.01.2010, 12:20 Uhr, schrieb bearophile <bearophileHUGS lycos.com>:It's not supposed to work, "dup" allocated memory with malloc, so it's (currently) a run time thing (in future this may change).So how to "create" an array expression at compile-time to enforce reinterpret_cast instead of conversion? // cast array literal const short[] ct = cast(short[]) [cast(byte)1, 1]; writeln(ct); // writes [1 1] // cast other array expression short[] rt = cast(short[]) [cast(byte)1, 1].dup; writeln(rt); // writes [257]
Jan 03 2010
Denis Koroskin:"Proper" code should look like this: short[] t = [cast(short) 5, cast(short)3]; which is err... I'll let someone else to decide. Just imagine there are ten (or more) values in an array literal.What's wrong with just (D2 code): short[] a3 = [5, 3]; Bye, bearophile
Jan 03 2010
bearophile schrieb:What's wrong with just (D2 code): short[] a3 = [5, 3];Nothing, but it's just the stripped down example. auto t = [0xFF, 0x00]; yields int[] so for struct Foo { ...} auto x = cast(Foo[]) [0x00, 0x01,...]; you need an additional cast(ubyte[]). Yet this doesn't work: http://codepad.org/P9EZ0dIB
Jan 03 2010
Trass3r:I was not answering you, but what Denis Koroskin has written. This thread is getting too much confused. And I think I have already seen a very similar thread elsewhere.What's wrong with just (D2 code): short[] a3 = [5, 3];Nothing, but it's just the stripped down example.auto t = [0xFF, 0x00]; yields int[]That's the correct thing. Ints are the default because D2 doesn't defaults to optimized multi-precision integral values as CLisp.Yet this doesn't work: http://codepad.org/P9EZ0dIBmodule main; import std.stdio, std.string; struct RGBA { ubyte r; ubyte g; ubyte b; ubyte a; string toString() { return format("{%s, %s, %s, %s}", r, g, b, a); } } static f = cast(RGBA[]) cast(ubyte[])[0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70]; static g = cast(RGBA[]) cast(ubyte[])[0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70].dup; enum h = cast(ubyte[])[0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70].dup; static h2 = cast(RGBA[]) h.dup; enum h3 = cast(RGBA[]) h; void main() { writeln(f); writeln(h2); writeln(h3); } I don't like that code. So, do you want to define an array of 4-bytes structs? What's wrong with: // qualified imports import std.stdio: writeln; import std.string: format; struct RGBA { ubyte r, g, b, a; string toString() { return format("{%s, %s, %s, %s}", r, g, b, a); } } // alternative 1: enum RGBA[] data1 = [{0x00, 0x10, 0x20, 0x30}, {0x40, 0x50, 0x60, 0x70}]; // alternative 2: enum RGBA[] data2 = [RGBA(0x00, 0x10, 0x20, 0x30), RGBA(0x40, 0x50, 0x60, 0x70)]; void main() { writeln(data1); writeln(data2); } Bye, bearophile
Jan 03 2010
Am 03.01.2010, 12:33 Uhr, schrieb bearophile <bearophileHUGS lycos.com>:// alternative 1: enum RGBA[] data1 = [{0x00, 0x10, 0x20, 0x30}, {0x40, 0x50, 0x60, 0x70}]; // alternative 2: enum RGBA[] data2 = [RGBA(0x00, 0x10, 0x20, 0x30), RGBA(0x40, 0x50, 0x60, 0x70)];Alternative 1: I heard struct literals could be removed. Alternative 2: 1) it's cumbersome, especially if you got a huge array 2) if you somehow fundamentally change the struct for whatever reason, you probably have to reassign everything. I currently use the old casting hack: auto PALETTE = (cast(RGBA*) cast(ubyte[]) [0xFF,...]) [0 .. 256]; I just ask if it's possible to do it in a nicer way, i.e. either 1) the current behavior needs to be changed so casting to arrays of structs always does a reinterpret_cast or 2) there must be some way to turn an array literal into an array expression at compile-time (i.e. without using .dup) to force reinterpretation.
Jan 03 2010
Trass3r:Alternative 1: I heard struct literals could be removed.I haven't heard that. They are recently changed a little, but you already know that from another thread.Alternative 2: 1) it's cumbersome, especially if you got a huge arrayBut it's clean & readable, and more flexible because later you can add a static opCall that does what you want. You can use a Python script or an IDE to generate the D code.I currently use the old casting hack: auto PALETTE = (cast(RGBA*) cast(ubyte[]) [0xFF,...]) [0 .. 256];This looks OK for a 20 lines long script for your personal usage, but I refuse it in production code. The code must be first of all tidy, and it must use a clean semantics, unless you have already profiled the code and found out that a spot is not fast enough for the program users. Unless otherwise required, you must program as your stereotypical granny drives, or later the code will bite your rear :-) Bye, bearophile
Jan 03 2010
Am 03.01.2010, 14:00 Uhr, schrieb bearophile <bearophileHUGS lycos.com>:Trass3r:I read somewhere it might conflict with function literals: {...}Alternative 1: I heard struct literals could be removed.I haven't heard that. They are recently changed a little, but you already know that from another thread.I don't need to be flexible. In this simple case I only need a reinterpret_cast. A good language like D should provide a neat, clean way to accomplish that without involving another language or tool (which in fact is already supported but it simply doesn't work at compile-time that way)Alternative 2: 1) it's cumbersome, especially if you got a huge arrayBut it's clean & readable, and more flexible because later you can add a static opCall that does what you want. You can use a Python script or an IDE to generate the D code.
Jan 03 2010
On Sun, 03 Jan 2010 06:53:53 -0500, Trass3r <un known.com> wrote:Am 03.01.2010, 12:33 Uhr, schrieb bearophile <bearophileHUGS lycos.com>:You should be able to do this I would think: auto PALETTE = cast(RGBA[])(cast(ubyte[])[0xFF,..])); but it doesn't work. I think it probably should. Why would I cast each element to byte only to then cast to RGBA. I think the parentheses should make it clear how I want the cast to proceed. I agree there should be a way to invoke the "bitwise" cast in one line besides the hackish way you are forced to do it. -Steve// alternative 1: enum RGBA[] data1 = [{0x00, 0x10, 0x20, 0x30}, {0x40, 0x50, 0x60, 0x70}]; // alternative 2: enum RGBA[] data2 = [RGBA(0x00, 0x10, 0x20, 0x30), RGBA(0x40, 0x50, 0x60, 0x70)];Alternative 1: I heard struct literals could be removed. Alternative 2: 1) it's cumbersome, especially if you got a huge array 2) if you somehow fundamentally change the struct for whatever reason, you probably have to reassign everything. I currently use the old casting hack: auto PALETTE = (cast(RGBA*) cast(ubyte[]) [0xFF,...]) [0 .. 256];
Jan 03 2010