digitalmars.D.learn - Using return type of a predicate function as a template
- Edwin van Leeuwen (33/33) Oct 16 2014 I am trying to implement a groupBy function that groups by the
- Atila Neves (26/60) Oct 16 2014 This works:
- Edwin van Leeuwen (3/14) Oct 16 2014 Thank you, that is surprisingly straightforward :)
I am trying to implement a groupBy function that groups by the return type of a predicate. Currently I have to define the returntype of the predicate for it to compile. Is there a way to get the return type at compile time and use it. The code: V[K] groupBy( alias func, K, V )( V values ) { V[K] grouped; foreach ( value ; values ) { grouped[func( value )] ~= value; } return grouped; } unittest { struct Test { string a; double b; } auto values = [Test( "a", 1 ), Test( "a", 2 ), Test( "b", 3 )]; auto grouped = values.groupBy!( (a) => a.a, string ); assert( grouped["a"].length == 2 ); assert( grouped["a"][1].b == 2 ); assert( grouped["b"].length == 1 ); assert( grouped["b"][0].b == 3 ); } So the above works, but I need to call it with: values.groupBy!( (a) => a.a, string ); Ideally I would call it instead with: values.groupBy!( (a) => a.a ) and it would infer that the template K needs to be a string, since that is the return type of (a) => a.a. Cheers, Edwin
Oct 16 2014
This works: import std.range; auto groupBy(alias func, R)(R values) if (isInputRange!R) { alias K = typeof(func(values.front)); alias V = ElementType!R[]; V[K] grouped; foreach(value; values) grouped[func(value)] ~= value; return grouped; } unittest { struct Test { string a; double b; } auto values = [Test( "a", 1 ), Test( "a", 2 ), Test( "b", 3 )]; auto grouped = values.groupBy!(a => a.a); assert( grouped["a"].length == 2 ); assert( grouped["a"][1].b == 2 ); assert( grouped["b"].length == 1 ); assert( grouped["b"][0].b == 3 ); } Atila On Thursday, 16 October 2014 at 08:04:08 UTC, Edwin van Leeuwen wrote:I am trying to implement a groupBy function that groups by the return type of a predicate. Currently I have to define the returntype of the predicate for it to compile. Is there a way to get the return type at compile time and use it. The code: V[K] groupBy( alias func, K, V )( V values ) { V[K] grouped; foreach ( value ; values ) { grouped[func( value )] ~= value; } return grouped; } unittest { struct Test { string a; double b; } auto values = [Test( "a", 1 ), Test( "a", 2 ), Test( "b", 3 )]; auto grouped = values.groupBy!( (a) => a.a, string ); assert( grouped["a"].length == 2 ); assert( grouped["a"][1].b == 2 ); assert( grouped["b"].length == 1 ); assert( grouped["b"][0].b == 3 ); } So the above works, but I need to call it with: values.groupBy!( (a) => a.a, string ); Ideally I would call it instead with: values.groupBy!( (a) => a.a ) and it would infer that the template K needs to be a string, since that is the return type of (a) => a.a. Cheers, Edwin
Oct 16 2014
On Thursday, 16 October 2014 at 08:18:02 UTC, Atila Neves wrote:This works: import std.range; auto groupBy(alias func, R)(R values) if (isInputRange!R) { alias K = typeof(func(values.front)); alias V = ElementType!R[]; V[K] grouped; foreach(value; values) grouped[func(value)] ~= value; return grouped; }Thank you, that is surprisingly straightforward :) Edwin
Oct 16 2014