digitalmars.D - Array of structs construction
- bearophile (39/39) Oct 19 2012 I'd like to write code like this (the constructors of the structs
- Era Scarecrow (29/51) Oct 19 2012 Only way i can see this working simply, is if it's auto, at
- H. S. Teoh (18/32) Oct 19 2012 [...]
- H. S. Teoh (23/42) Oct 19 2012 [...]
- H. S. Teoh (20/30) Oct 19 2012 [...]
- bearophile (5/9) Oct 21 2012 I have 2D array literals. Thank you for your work. It shows how
- timotheecour (22/22) Oct 22 2012 Can't we simply use map, so as not to introduce new syntax?
- bearophile (13/14) Oct 23 2012 This works today:
- Maxim Fomin (33/39) Oct 23 2012 Syntax construct a=>b causes nasty bug covered up by map
I'd like to write code like this (the constructors of the structs must take 1 argument): // some imports here void main() { BigInt[] data1 = [5, 6, 9]; Ranged!(int,5,10)[] data2 = [5, 6, 9]; Nibble[] data3 = [1, 2, 15]; // Nibble.sizeof == 1 alias Typedef!int Mint; Mint[] data4 = [5, 6, 9]; } Do you like this feature? Scala accepts a similar syntax: http://ideone.com/mFuVxP // Scala code object Main extends App { val data : Array[BigInt] = Array(10, 20, 30) } Currently in D you write this, it's not handy if you have many items: // some imports here void main() { auto data1 = [BigInt(5), BigInt(6), BigInt(9)]; alias Ranged!(int,5,10) R; // a short name auto data2 = [R(5), R(6), R(9)]; auto data3 = [Nibble(1), Nibble(2), Nibble(15)]; alias Typedef!int Mint; Mint[] data4 = [Mint(5), Mint(6), Mint(9)]; } Or you duplicate the arrays to avoid the bit liberals: import std.bigint; void main() { auto aux = [5, 6, 9]; auto data1 = new BigInt[aux.length]; foreach (i, a; aux) data1[i] = BigInt(a); // ... } Bye, bearophile
Oct 19 2012
On Saturday, 20 October 2012 at 01:06:57 UTC, bearophile wrote:I'd like to write code like this (the constructors of the structs must take 1 argument): // some imports here void main() { BigInt[] data1 = [5, 6, 9]; Ranged!(int,5,10)[] data2 = [5, 6, 9]; Nibble[] data3 = [1, 2, 15]; // Nibble.sizeof == 1 alias Typedef!int Mint; Mint[] data4 = [5, 6, 9]; } Do you like this feature? Currently in D you write this, it's not handy if you have many items: // some imports here void main() { auto data1 = [BigInt(5), BigInt(6), BigInt(9)]; alias Ranged!(int,5,10) R; // a short name auto data2 = [R(5), R(6), R(9)]; auto data3 = [Nibble(1), Nibble(2), Nibble(15)]; alias Typedef!int Mint; Mint[] data4 = [Mint(5), Mint(6), Mint(9)]; }Only way i can see this working simply, is if it's auto, at least one of the items have to specify it's full type and the rest can be ignored. Also it must have a constructor that takes that one type of argument. So.. //50 & 100 aren't BigInt, but can be constructed to be one.. auto bignums = [BigInt(25), 50, 100]; As for above arrays where the type is known, I can't see a reason why it can't work. In a large array of static data I've had to make shortcut names for several structs in order to keep it readable and programmable. This may help in some cases, or perhaps all of them. Course this also means if a structure is being initialized then perhaps it can be extended. Like the above, except... struct S { int x,y; BigInt z; } S s = {1,2,3}; //3 converted if BigInt has a constructor for int //if that's illegal, then you'd do this to make it work instead, //which seems... unnecessary. struct S { int x,y; BigInt[1] z; } S s = {1,2,[3]}; The downside is if there's memory allocation or heavy work that can't be done at compile-time then there may be more complex issues trying to optimize something. Makes it sorta mixed.
Oct 19 2012
On Sat, Oct 20, 2012 at 03:06:56AM +0200, bearophile wrote:I'd like to write code like this (the constructors of the structs must take 1 argument): // some imports here void main() { BigInt[] data1 = [5, 6, 9]; Ranged!(int,5,10)[] data2 = [5, 6, 9]; Nibble[] data3 = [1, 2, 15]; // Nibble.sizeof == 1 alias Typedef!int Mint; Mint[] data4 = [5, 6, 9]; } Do you like this feature?[...] What about mixin() with a CTFE function that expands an array of initializers at compile-time? Something like: string structArray(S,T...)(T args) if (is(typeof(S(args[0])))) { // Warning: untested code return "[" ~ join( map!(a) => S.stringof ~ "(" ~ a ~ ")", ",") ~ "]"; } S[] sArr = mixin(structArray(elem0, elem1, elem2)); T -- English has the lovely word "defenestrate", meaning "to execute by throwing someone out a window", or more recently "to remove Windows from a computer and replace it with something useful". :-) -- John Cowan
Oct 19 2012
On Fri, Oct 19, 2012 at 10:32:48PM -0700, H. S. Teoh wrote:On Sat, Oct 20, 2012 at 03:06:56AM +0200, bearophile wrote:[...] OK, here's a tested, working example: import std.stdio; string structArray(S)(string[] args...) { string s = "["; string delim = ""; foreach (a; args) { s ~= delim ~ S.stringof ~ "(" ~ a ~ ")"; delim = ","; } return s ~ "]"; } struct AStruct { int x, y; } void main() { AStruct[] arr = mixin(structArray!AStruct("1,1", "1,2", "2,2", "2,3")); writeln(arr); } T -- "Life is all a great joke, but only the brave ever get the point." -- Kenneth RexrothI'd like to write code like this (the constructors of the structs must take 1 argument): // some imports here void main() { BigInt[] data1 = [5, 6, 9]; Ranged!(int,5,10)[] data2 = [5, 6, 9]; Nibble[] data3 = [1, 2, 15]; // Nibble.sizeof == 1 alias Typedef!int Mint; Mint[] data4 = [5, 6, 9]; } Do you like this feature?[...] What about mixin() with a CTFE function that expands an array of initializers at compile-time? Something like:
Oct 19 2012
On Fri, Oct 19, 2012 at 10:42:08PM -0700, H. S. Teoh wrote: [...]import std.stdio; string structArray(S)(string[] args...) { string s = "["; string delim = ""; foreach (a; args) { s ~= delim ~ S.stringof ~ "(" ~ a ~ ")"; delim = ","; } return s ~ "]"; }[...] Here's how to use it for making BigInt arrays: void main() { BigInt[] arr = mixin(structArray!BigInt( `"12345678901234567890"`, `"4294967296000"`, `"1000000000000000000000000000000000"`, `"1203004000500006000007000000800000009"`, )); writeln(arr); } It works for any kind of struct with ctors. Should be trivially extendible to array of class objects. Some improvement in usage syntax is probably possible, too, but I'll leave it up to the CTFE experts here to figure that out. ;-) T -- Why ask rhetorical questions? -- JC
Oct 19 2012
H. S. Teoh:It works for any kind of struct with ctors. Should be trivially extendible to array of class objects. Some improvement in usage syntax is probably possible, too, but I'll leave it up to the CTFE experts here to figure that out. ;-)I have 2D array literals. Thank you for your work. It shows how far you go with library code. Bye, bearophile
Oct 21 2012
Can't we simply use map, so as not to introduce new syntax? import std.algorithm:map; import std.array:array; // some imports here void main() { //BigInt[] data1 = [5, 6, 9]; auto data1 = [5, 6, 9].map!(a=>BigInt(a)).array; Ranged!(int,5,10)[] data2 = [5, 6, 9]; auto data2 = [5, 6, 9].map!(a=>Ranged!(int,5,10)).array; } I think this is less verbose than something like: AStruct[] arr = mixin(structArray!AStruct("1,1", "1,2", "2,2", "2,3")); Also, we can make it even more concise by: auto data1 = [5, 6, 9].map!(make!BigInt).array; //make has been proposed as a proxy to construct a struct/class or even the very concise: auto data1 = [5, 6, 9].mapMake!BigInt; where mapMake would be similar to std.algorithm.map except it would take a struct (or class) type instead of a delegate. It's code should be fairly obvious. We could choose whether to return a lazy range or not in that case so the ".array" is not required.
Oct 22 2012
timotheecour:Can't we simply use map, so as not to introduce new syntax?This works today: import std.algorithm, std.array, std.bigint; void main() { auto data1 = [5, 6, 9].map!BigInt().array(); } But literals like: Ranged!(int,2,20)[] data2 = [5, 6, 9]; Are useful to make the code stronger, because the invariant of that Ranged is verified statically, despite data2 is not an enum. Right? Bye, bearophile
Oct 23 2012
On Tuesday, 23 October 2012 at 04:51:01 UTC, timotheecour wrote:void main() { //BigInt[] data1 = [5, 6, 9]; auto data1 = [5, 6, 9].map!(a=>BigInt(a)).array; Ranged!(int,5,10)[] data2 = [5, 6, 9]; auto data2 = [5, 6, 9].map!(a=>Ranged!(int,5,10)).array; }Syntax construct a=>b causes nasty bug covered up by map template. It is related to 8854, 8832 and 7978 and several topics at forum associated with these issues (strange behavior using map together with delegates). The problem is that typeless undeclared identifier "a" causes syntax construct a=>b to be of type void rather than delegate. Once syntax is fixed, type of expression becomes as expected http://dpaste.dzfl.pl/738f7301 Sometimes this leads to observable incorrect behavior, sometimes not. For example, if you have -----main.d-------------- version (bug) { import std.string; } import test; void main() { testfun(); } -------test.d----------------- import std.algorithm; import std.stdio; void testfun() { int c = 0; writeln([0].map!(a=>c)[0]); } ----------------------------- then the behavior of program would depend on whether bug version is set or not.
Oct 23 2012