www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - How to specialize template function for associative arrays?

reply Aarti_pl <aarti interia.pl> writes:
void parse(T)() {
}

//What to write here???
void parse(T : ?????)() {
}

void main() {
     parse!(int[char[]])();
}
Oct 19 2007
next sibling parent reply Extrawurst <spam extrawurst.org> writes:
as far as i know:

void parse(T : A[B])() {
}

~Extrawurst


Aarti_pl schrieb:
 void parse(T)() {
 }

 //What to write here???
 void parse(T : ?????)() {
 }

 void main() {
     parse!(int[char[]])();
 }

Oct 19 2007
parent reply Aarti_pl <aarti interia.pl> writes:
Extrawurst pisze:
 as far as i know:
 
 void parse(T : A[B])() {
 }
 
 ~Extrawurst
 
 

Unfortunately not... I was also thinking that it will work, but you get compile time error instead: quicktest.d(13): Error: identifier 'B' is not defined quicktest.d(13): Error: index is not a type or an expression quicktest.d(13): Error: identifier 'A' is not defined quicktest.d(13): Error: A is used as a type I managed to catch associative arrays with 'static if' and templates, but it would be better to use template specialization to have better source code structure. Any other ideas? BR Marcin Kuszczak
Oct 19 2007
parent reply Regan Heath <regan netmail.co.nz> writes:
Aarti_pl wrote:
 Extrawurst pisze:
 as far as i know:

 void parse(T : A[B])() {
 }

 ~Extrawurst

Unfortunately not... I was also thinking that it will work, but you get compile time error instead: quicktest.d(13): Error: identifier 'B' is not defined quicktest.d(13): Error: index is not a type or an expression quicktest.d(13): Error: identifier 'A' is not defined quicktest.d(13): Error: A is used as a type I managed to catch associative arrays with 'static if' and templates, but it would be better to use template specialization to have better source code structure. Any other ideas?

Does parse really have no arguments? Or does it actally look a bit like: import std.stdio; void parse(T)(T t) { writefln("parse(T)"); } void parse(V, K)(V[K] arr) { writefln("parse(V, K)"); } void main() { int[char[]] arr; parse!(int, char[])(arr); } Regan
Oct 19 2007
parent reply Aarti_pl <aarti interia.pl> writes:
Regan Heath pisze:
 Aarti_pl wrote:
 Extrawurst pisze:
 as far as i know:

 void parse(T : A[B])() {
 }

 ~Extrawurst

Unfortunately not... I was also thinking that it will work, but you get compile time error instead: quicktest.d(13): Error: identifier 'B' is not defined quicktest.d(13): Error: index is not a type or an expression quicktest.d(13): Error: identifier 'A' is not defined quicktest.d(13): Error: A is used as a type I managed to catch associative arrays with 'static if' and templates, but it would be better to use template specialization to have better source code structure. Any other ideas?

Does parse really have no arguments? Or does it actally look a bit like: import std.stdio; void parse(T)(T t) { writefln("parse(T)"); } void parse(V, K)(V[K] arr) { writefln("parse(V, K)"); } void main() { int[char[]] arr; parse!(int, char[])(arr); } Regan

Nope. I just want to choose proper template function depending on parameter type (in this case associative array). It should be something similar to: void parse(T : T[])() { writefln("parse(T[])"); } which actually works. Maybe it is just doesn't work in D? ----------- BTW: above syntax for normal arrays looks for me not very consistent. In fact it should be: # void parse(T : E[])() { # writefln("Type: ", T.stringof, " Element type: ", A.stringof); # } and then proposal from Extrawurst would be just logical consequence. BR Marcin
Oct 19 2007
next sibling parent Aarti_pl <aarti interia.pl> writes:
Aarti_pl pisze:

 Nope. I just want to choose proper template function depending on 
 parameter type (in this case associative array).

Depending on previously instantiated template's type argument. (I just realized that my previous statement does not make much sense... Hopefully this approach will make more sense, although is not much easier to read. :-O) BR Marcin
Oct 19 2007
prev sibling parent reply Bill Baxter <dnewsgroup billbaxter.com> writes:
Aarti_pl wrote:
 -----------
 
 BTW: above syntax for normal arrays looks for me not very consistent. In 
 fact it should be:
 # void parse(T : E[])() {
 #     writefln("Type: ", T.stringof, " Element type: ", A.stringof);
 # }
 
 and then proposal from Extrawurst would be just logical consequence.

I agree with you. T:E[] can be read as "T where T is an E[] for some E". Very logical. With T:T[] I never can remember if the T I get in the function is the type passed in or the type without the []. It's the full type right? So the :T[] really only means "where T is an array", and the reuse of T is just a distractor. T:array would maybe be more to the point. Oh, no wait, it's the other way isn't it. The function gets the T stripped of []. Gaaahh! The is() syntax is also very odd if (is(T S : S[])) { // S now an alias of T stripped of its [] } I think it would be more logical as if (is(S; T : S[])) { // S now an alias of T stripped of its [] } The S; is reminiscent of the first clause of foreach where you can declare new scoped symbols whose meaning is derived from what's on the right of the ';'. So that's read "we're declaring a new S, where S is the type such that T is S[]. I think that would also make things like is(F Args == function) a bit more logical too. Currently it looks an awful lot like "Args equals a function" but it means we're defining a new Args to be the parameters of the function F? Huh? Compare with is(Args; F==function) "Checking if F is a function and also declaring a new Args whose type is deduced from F" --bb
Oct 19 2007
parent Daniel Keep <daniel.keep.lists gmail.com> writes:
Bill Baxter wrote:
 Aarti_pl wrote:
 -----------

 BTW: above syntax for normal arrays looks for me not very consistent.
 In fact it should be:
 # void parse(T : E[])() {
 #     writefln("Type: ", T.stringof, " Element type: ", A.stringof);
 # }

 and then proposal from Extrawurst would be just logical consequence.

I agree with you. T:E[] can be read as "T where T is an E[] for some E". Very logical. With T:T[] I never can remember if the T I get in the function is the type passed in or the type without the []. It's the full type right? So the :T[] really only means "where T is an array", and the reuse of T is just a distractor. T:array would maybe be more to the point. Oh, no wait, it's the other way isn't it. The function gets the T stripped of []. Gaaahh!

I've never really had a problem with it. I think of T:T[] as being "given the user passed in T[], give me T." Granted, I know how you feel; there've been many things in my life that have confused me until I came up with a good way of remembering them.
 The is() syntax is also very odd
    if (is(T S : S[])) {
        // S now an alias of T stripped of its []
    }
 
 I think it would be more logical as
    if (is(S;  T : S[])) {
        // S now an alias of T stripped of its []
    }

I do agree that the current syntax is a bit weird, but I can't say I like your solution. :3 I look at it, and I can't quite work out what it's trying to say.
 The S; is reminiscent of the first clause of foreach where you can
 declare new scoped symbols whose meaning is derived from what's on the
 right of the ';'.  So that's read "we're declaring a new S, where S is
 the type such that T is S[].
 
 I think that would also make things like  is(F Args == function) a bit
 more logical too.
 Currently it looks an awful lot like "Args equals a function" but it
 means we're defining a new Args to be the parameters of the function F?
  Huh?  Compare with
      is(Args; F==function)
 "Checking if F is a function and also declaring a new Args whose type is
 deduced from F"
 
 --bb

I suppose is() and specialisation could use improvement. I guess I'm just reticent to make sweeping changes to something that I've gotten used to. Plus it means you won't be able to make templates that work in both D 1.0 and D 2.0! -- Daniel
Oct 19 2007
prev sibling parent reply Extrawurst <spam extrawurst.org> writes:
what about just this :

void foo(A, B)(A[B] _aa)
{
    foreach(it; _aa)
    {
        writefln("%s",it);
    }
}

void main()
{
    string[int] bar = [2:"test"[], 55:"bar"];

    foo!(string,int)(bar);

    writefln("byye");
}


~Extrawurst



Aarti_pl schrieb:
 void parse(T)() {
 }

 //What to write here???
 void parse(T : ?????)() {
 }

 void main() {
     parse!(int[char[]])();
 }

Oct 19 2007
parent Marcin Kuszczak <aarti_nospam please_interia.pl> writes:
Extrawurst wrote:

 what about just this :
 
 void foo(A, B)(A[B] _aa)
 {
     foreach(it; _aa)
     {
         writefln("%s",it);
     }
 }
 
 void main()
 {
     string[int] bar = [2:"test"[], 55:"bar"];
 
     foo!(string,int)(bar);
 
     writefln("byye");
 }
 
 
 ~Extrawurst

It will not work. Instantiation should be same for all types... I found following solution: void parse(T)() { static if (isAssociativeArray(T)) { .... } else { .... } } Template isAssociativeArray(T) is from Tango/core/traits.d. (Thank you, Tango team!). Thanks to this template I could also get key type and value type of associative array. Anyway I think that it should work somehow for specializations, so I will put enhancement request on bugzilla. -- Regards Marcin Kuszczak (Aarti_pl) ------------------------------------- Ask me why... I believe in Jesus - http://www.zapytajmnie.com (en/pl) Doost (port of few Boost libraries) - http://www.dsource.org/projects/doost/ -------------------------------------
Oct 19 2007