| Thread overview | ||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
January 21, 2008 Templates and Associative Arrays | ||||
|---|---|---|---|---|
| ||||
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.
| ||||
January 21, 2008 Re: Templates and Associative Arrays | ||||
|---|---|---|---|---|
| ||||
Posted in reply to dsimcha | dsimcha <dsimcha@yahoo.com> 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. 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 == "void")?"":U.stringof) ~ "][" ~ ((V.stringof == "void")?"":V.stringof) ~ "] data, size_t column_to_extract) { T[] extracted_column; foreach(row; data) { extracted_column~=row[column_to_extract]; } return extracted_column; }"); } alias foo!(int, void, void) bar; int main() { int[][] baz; baz.length = 1; baz[0].length = 1; baz[0][0] = 4; auto foobar = 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 | |||
January 21, 2008 Re: Templates and Associative Arrays | ||||
|---|---|---|---|---|
| ||||
Posted in reply to dsimcha | 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
| |||
January 21, 2008 Re: Templates and Associative Arrays - disregard the above post; this one has working code. | ||||
|---|---|---|---|---|
| ||||
Posted in reply to downs | 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
| |||
January 22, 2008 Re: Templates and Associative Arrays - disregard the above post; this one has working code. | ||||
|---|---|---|---|---|
| ||||
Posted in reply to downs | 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. | |||
January 22, 2008 Re: Templates and Associative Arrays - boring version | ||||
|---|---|---|---|---|
| ||||
Posted in reply to dsimcha | 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 | |||
January 22, 2008 Re: Templates and Associative Arrays - boring version | ||||
|---|---|---|---|---|
| ||||
Posted in reply to downs | downs wrote:
> 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
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;
}
| |||
January 22, 2008 Re: Templates and Associative Arrays - boring version | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Don Clugston | 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
| |||
Copyright © 1999-2021 by the D Language Foundation
Permalink
Reply