digitalmars.D - Templates and Associative Arrays
- dsimcha (18/18) Jan 20 2008 Is it possible to create a template function that treats regular dynamic
- Simen Kjaeraas (42/66) Jan 20 2008 a =
- downs (16/36) Jan 21 2008 Sure :)
- downs (4/17) Jan 21 2008 Hope it helps.
- dsimcha (8/8) Jan 21 2008 Wow, that is an impressive hack. While it's certainly better than nothi...
- downs (3/28) Jan 22 2008 --downs
- Don Clugston (8/38) Jan 22 2008 Do you really need the Init template ? Why not just:
- downs (3/8) Jan 22 2008 Thanks. I wasn't aware that you could use types like that. Kind of unint...
Is it possible to create a template function that treats regular dynamic arrays the same as associative arrays? For example, I want to create a very simple template function to extract a column from a 2-d array of T's. If the array is non-associative in both dimensions, the function could be trivially implemented as: T[] extract_column(T)(T[][] data, size_t column_to_extract) { T[] extracted_column; foreach(row; data) { extracted_column~=row[column_to_extract]; } return extracted_column; } However, in the case of an associatve array, I cannot think of any obvious way to make this work without essentially implementing it four different times, once each for an associative and non-associative row dimension and likewise for the column dimension.
Jan 20 2008
dsimcha <dsimcha yahoo.com> wrote:Is it possible to create a template function that treats regular dynam=icarrays the same as associative arrays? For example, I want to create =a =very simple template function to extract a column from a 2-d array of T's. ==If the array is non-associative in both dimensions, the function could be =trivially implemented as: T[] extract_column(T)(T[][] data, size_t column_to_extract) { T[] extracted_column; foreach(row; data) { extracted_column~=3Drow[column_to_extract]; } return extracted_column; } However, in the case of an associatve array, I cannot think of any =obvious way to make this work without essentially implementing it four different =times, once each for an associative and non-associative row dimension and =likewise for the column dimension.If you're asking whether there is some uniform way to declare an = associative and a normal dynamic array, then I fear you're out of luck. = = Perhaps this should be possible by some strange magic like int[void] foo= ; = to declare a normal array... I did make a template that works though, but it's an ugly way to do this= : template foo(T, U, V) { mixin("T[] extract_column(T[" ~ ((U.stringof =3D=3D "void")?"":U.string= of) ~ = "][" ~ ((V.stringof =3D=3D "void")?"":V.stringof) ~ "] data, size_t = column_to_extract) { T[] extracted_column; foreach(row; data) { extracted_column~=3Drow[column_to_extract]; } return extracted_column; }"); } alias foo!(int, void, void) bar; int main() { int[][] baz; baz.length =3D 1; baz[0].length =3D 1; baz[0][0] =3D 4; auto foobar =3D bar.extract_column(baz, 0); writefln(foobar); = return 0; } prints [4] This might be possible to do in a better way, of course. Simen Kjaeraas
Jan 20 2008
dsimcha wrote:Is it possible to create a template function that treats regular dynamic arrays the same as associative arrays? For example, I want to create a very simple template function to extract a column from a 2-d array of T's. If the array is non-associative in both dimensions, the function could be trivially implemented as: T[] extract_column(T)(T[][] data, size_t column_to_extract) { T[] extracted_column; foreach(row; data) { extracted_column~=row[column_to_extract]; } return extracted_column; } However, in the case of an associatve array, I cannot think of any obvious way to make this work without essentially implementing it four different times, once each for an associative and non-associative row dimension and likewise for the column dimension.Sure :) Keep in mind, this code isn't tested .. but it should work in theory. template Init(T) { T Init; } import std.traits; template NestedArrayElemType(T) { // this uses return-type autodeduction to basically say "if we iterated over the elements of T, and returned elem2; what would its type be?" alias ReturnType({ foreach (elem; Init!(T)) foreach (elem2; elem) return elem2; }) NestedArrayElemType; } alias NestedArrayElemType naet; naet!(T) extract_column(T)(T data, size_t which) { naet!(T) res; foreach (row; data) res ~= row[which]; return res; } --downs
Jan 21 2008
Agh. Too many mistakes. Sorry. Here's some working, tested code instead.import std.stdio, std.traits; template Init(T) { T Init; } template NAET(T) { alias ReturnType!({ foreach (elem; Init!(T)) foreach (elem2; elem) return elem2; }) NAET; } void main() { writefln(NAET!(int[][]).stringof); writefln(NAET!(int[][int]).stringof); writefln(NAET!(float[string][]).stringof); }Hope it helps. --downs
Jan 21 2008
Wow, that is an impressive hack. While it's certainly better than nothing, this is one area where it would be nice if the template system in D improved to make this cleaner and more obvious. I am trying to learn/use D to replace scripting languages for programs involving huge CSV files, because the scripting languages are painfully slow for this. I have a small custom library in PHP (which I use for general-purpose, not just web, scripting) for handling CSVs, and am trying to port it to D, and creating simple, clean templates for processing arrays without knowing at compile time whether they are regular or associative is a major hangup.
Jan 21 2008
dsimcha wrote:Wow, that is an impressive hack. While it's certainly better than nothing, this is one area where it would be nice if the template system in D improved to make this cleaner and more obvious. I am trying to learn/use D to replace scripting languages for programs involving huge CSV files, because the scripting languages are painfully slow for this. I have a small custom library in PHP (which I use for general-purpose, not just web, scripting) for handling CSVs, and am trying to port it to D, and creating simple, clean templates for processing arrays without knowing at compile time whether they are regular or associative is a major hangup.Alright, so here's the boring version :)import std.stdio; template Init(T) { T Init; } template ElemType(T) { static if (is(typeof(Init!(T).keys))) alias typeof(Init!(T)[Init!(T).keys[0]]) ElemType; else alias typeof(Init!(T)[0]) ElemType; } void main() { writefln(ElemType!(ElemType!(int[][])).stringof); writefln(ElemType!(ElemType!(float[string][string])).stringof); writefln(ElemType!(ElemType!(real[float][])).stringof); }--downs
Jan 22 2008
downs wrote:dsimcha wrote:Do you really need the Init template ? Why not just: template ElemType(T) { static if (is(typeof(T.keys))) alias typeof(T[T.keys[0]]) ElemType; else alias typeof(T[0]) ElemType; }Wow, that is an impressive hack. While it's certainly better than nothing, this is one area where it would be nice if the template system in D improved to make this cleaner and more obvious. I am trying to learn/use D to replace scripting languages for programs involving huge CSV files, because the scripting languages are painfully slow for this. I have a small custom library in PHP (which I use for general-purpose, not just web, scripting) for handling CSVs, and am trying to port it to D, and creating simple, clean templates for processing arrays without knowing at compile time whether they are regular or associative is a major hangup.Alright, so here's the boring version :)import std.stdio; template Init(T) { T Init; } template ElemType(T) { static if (is(typeof(Init!(T).keys))) alias typeof(Init!(T)[Init!(T).keys[0]]) ElemType; else alias typeof(Init!(T)[0]) ElemType; } void main() { writefln(ElemType!(ElemType!(int[][])).stringof); writefln(ElemType!(ElemType!(float[string][string])).stringof); writefln(ElemType!(ElemType!(real[float][])).stringof); }--downs
Jan 22 2008
Don Clugston wrote:Do you really need the Init template ? Why not just: template ElemType(T) { static if (is(typeof(T.keys))) alias typeof(T[T.keys[0]]) ElemType;Thanks. I wasn't aware that you could use types like that. Kind of unintuitive, don't you think? :) --downs
Jan 22 2008