digitalmars.D - Template currying
- Yuxuan Shui (30/30) May 05 2016 So I was working on a parser combinator library, where the
- Ed (9/40) May 05 2016 It's hard to help without a minimal working example (maybe
- Yuxuan Shui (8/18) May 05 2016 Simple example:
- Ed (4/25) May 05 2016 alias aa(T) = a!(1,T);
- Yuxuan Shui (5/37) May 05 2016 As you can see in my first post, I know how to make this work. I
- Yuxuan Shui (10/50) May 05 2016 See this example:
- Ed (8/9) May 05 2016 That's clear that you've never been stuck in the fat mud of
- Yuxuan Shui (4/13) May 05 2016 I'll do that, but I just want to see some feedback on this
- Ed (3/19) May 05 2016 Sorry, I don't know why I thought this thread was on d.learn, I
- Yuxuan Shui (3/28) May 05 2016 Wait, I just realized that this example works in 2.071, but not
- Yuxuan Shui (3/21) May 05 2016 Apply{Left, Right} is add in 2.071 as well, and I didn't see them
- Yuxuan Shui (5/27) May 05 2016 Oh, sorry, that doesn't work. My mistake.
- Yuxuan Shui (7/21) May 05 2016 I figured it out, here is a prototype of Curry:
- Ed (18/58) May 05 2016 My bad, I didn't read carefully "or not use alias:".
- Yuxuan Shui (5/38) May 05 2016 Right, Partial!() works. I just want something more generic, like
- ZombineDev (20/51) May 05 2016 alias can automatically introduce template arguments only for
So I was working on a parser combinator library, where the combinators take parsers as template argument. It works well until recently I decided to change the parsers so they would take Ranges instead of just strings. The combinator used to look like: template Comb(alias parser1, alias parser2) Now it looks like template Comb(alias parser1, alias parser2, Range) And I want to have the compile deduce the Range template arguments, so I don't need to change the code that uses them. But I found out it's hard to partially instantiate templates. It's OK to do that at the call site, e.g. Comb!(a, b)(range) works without specifying the Range. But sometimes I want to alias the result parser so I can use it at multiple places, but alias new_parser = Comb!(a, b); doesn't work. I need either to define Comb differently: template Comb(alias p1, alias p2) { template Comb(Range) { or not use alias: template new_parser(alias p1, alias p2){ alias new_parser(Range) = Comb!(p1, p2, Range); //Something like this, not tested } I think it would be really nice if alias can be automatically translated to the latter one. Or maybe we can have something like template Curry(alias tmpl, Args1...) { alias Curry(Args2...) = tmpl!(Args1~Args2); //Pseudocode } in the phobos.
May 05 2016
On Thursday, 5 May 2016 at 20:17:08 UTC, Yuxuan Shui wrote:So I was working on a parser combinator library, where the combinators take parsers as template argument. It works well until recently I decided to change the parsers so they would take Ranges instead of just strings. The combinator used to look like: template Comb(alias parser1, alias parser2) Now it looks like template Comb(alias parser1, alias parser2, Range) And I want to have the compile deduce the Range template arguments, so I don't need to change the code that uses them. But I found out it's hard to partially instantiate templates. It's OK to do that at the call site, e.g. Comb!(a, b)(range) works without specifying the Range. But sometimes I want to alias the result parser so I can use it at multiple places, but alias new_parser = Comb!(a, b); doesn't work. I need either to define Comb differently: template Comb(alias p1, alias p2) { template Comb(Range) { or not use alias: template new_parser(alias p1, alias p2){ alias new_parser(Range) = Comb!(p1, p2, Range); //Something like this, not tested } I think it would be really nice if alias can be automatically translated to the latter one. Or maybe we can have something like template Curry(alias tmpl, Args1...) { alias Curry(Args2...) = tmpl!(Args1~Args2); //Pseudocode } in the phobos.It's hard to help without a minimal working example (maybe something with just the body). If you mean that "alias new_parser = Comb!(a, b);" generates an error maybe that's because the correct syntax is "alias new_parser(Range) = Comb!(a, b);" ? One issue you may encounter is that template parameter deduction (that's called IFTI I think) can fail with an alias (so partially specialized template/templatized function, etc).
May 05 2016
On Thursday, 5 May 2016 at 21:54:29 UTC, Ed wrote:On Thursday, 5 May 2016 at 20:17:08 UTC, Yuxuan Shui wrote:Simple example: int a(int b, T)(T c){return 0;} It's fine to: a!1(2); But: alias A = a!1; Would fail.[...]It's hard to help without a minimal working example (maybe something with just the body). If you mean that "alias new_parser = Comb!(a, b);" generates an error maybe that's because the correct syntax is "alias new_parser(Range) = Comb!(a, b);" ? One issue you may encounter is that template parameter deduction (that's called IFTI I think) can fail with an alias (so partially specialized template/templatized function, etc).
May 05 2016
On Thursday, 5 May 2016 at 22:53:01 UTC, Yuxuan Shui wrote:On Thursday, 5 May 2016 at 21:54:29 UTC, Ed wrote:alias aa(T) = a!(1,T); aa!ubyte(2); Your alias declaration is not correct.On Thursday, 5 May 2016 at 20:17:08 UTC, Yuxuan Shui wrote:Simple example: int a(int b, T)(T c){return 0;} It's fine to: a!1(2); But: alias A = a!1; Would fail.[...]It's hard to help without a minimal working example (maybe something with just the body). If you mean that "alias new_parser = Comb!(a, b);" generates an error maybe that's because the correct syntax is "alias new_parser(Range) = Comb!(a, b);" ? One issue you may encounter is that template parameter deduction (that's called IFTI I think) can fail with an alias (so partially specialized template/templatized function, etc).
May 05 2016
On Thursday, 5 May 2016 at 23:12:40 UTC, Ed wrote:On Thursday, 5 May 2016 at 22:53:01 UTC, Yuxuan Shui wrote:As you can see in my first post, I know how to make this work. I just think it'd be nice if compiler can do this automatically. Anothor point is that, what if I want to use partially instantiated templates as template arguments?On Thursday, 5 May 2016 at 21:54:29 UTC, Ed wrote:alias aa(T) = a!(1,T); aa!ubyte(2); Your alias declaration is not correct.On Thursday, 5 May 2016 at 20:17:08 UTC, Yuxuan Shui wrote:Simple example: int a(int b, T)(T c){return 0;} It's fine to: a!1(2); But: alias A = a!1; Would fail.[...]It's hard to help without a minimal working example (maybe something with just the body). If you mean that "alias new_parser = Comb!(a, b);" generates an error maybe that's because the correct syntax is "alias new_parser(Range) = Comb!(a, b);" ? One issue you may encounter is that template parameter deduction (that's called IFTI I think) can fail with an alias (so partially specialized template/templatized function, etc).
May 05 2016
On Thursday, 5 May 2016 at 23:19:59 UTC, Yuxuan Shui wrote:On Thursday, 5 May 2016 at 23:12:40 UTC, Ed wrote:See this example: int a(alias f)(){return f(3);} int b(int z, T)(T c){return c;} void main() { a!(b!1)(); } It'd really nice if this just works, or if there's something called Curry which I can use like this: a!(Curry!(b, 1))On Thursday, 5 May 2016 at 22:53:01 UTC, Yuxuan Shui wrote:As you can see in my first post, I know how to make this work. I just think it'd be nice if compiler can do this automatically. Anothor point is that, what if I want to use partially instantiated templates as template arguments?On Thursday, 5 May 2016 at 21:54:29 UTC, Ed wrote:alias aa(T) = a!(1,T); aa!ubyte(2); Your alias declaration is not correct.On Thursday, 5 May 2016 at 20:17:08 UTC, Yuxuan Shui wrote:Simple example: int a(int b, T)(T c){return 0;} It's fine to: a!1(2); But: alias A = a!1; Would fail.[...]It's hard to help without a minimal working example (maybe something with just the body). If you mean that "alias new_parser = Comb!(a, b);" generates an error maybe that's because the correct syntax is "alias new_parser(Range) = Comb!(a, b);" ? One issue you may encounter is that template parameter deduction (that's called IFTI I think) can fail with an alias (so partially specialized template/templatized function, etc).
May 05 2016
On Thursday, 5 May 2016 at 23:33:07 UTC, Yuxuan Shui wrote:It'd really nice if this just works,That's clear that you've never been stuck in the fat mud of imperative and OO programming styles. You don't realize (anymore ?) how lucky we are with D templates, compared to other languages! Maybe you come from C++, so that's not so obvious for you but with my background I'm still amused when I see people complaining about such details. ^^ Anyway, you can open a enhancement request and pray...
May 05 2016
On Thursday, 5 May 2016 at 23:46:59 UTC, Ed wrote:On Thursday, 5 May 2016 at 23:33:07 UTC, Yuxuan Shui wrote:Yes, I do appreciate the power of D, I just want it to be BETTER.It'd really nice if this just works,That's clear that you've never been stuck in the fat mud of imperative and OO programming styles. You don't realize (anymore ?) how lucky we are with D templates, compared to other languages! Maybe you come from C++, so that's not so obvious for you but with my background I'm still amused when I see people complaining about such details. ^^Anyway, you can open a enhancement request and pray...I'll do that, but I just want to see some feedback on this idea....
May 05 2016
On Friday, 6 May 2016 at 00:08:01 UTC, Yuxuan Shui wrote:On Thursday, 5 May 2016 at 23:46:59 UTC, Ed wrote:Sorry, I don't know why I thought this thread was on d.learn, I didn't get this was a general discussion.On Thursday, 5 May 2016 at 23:33:07 UTC, Yuxuan Shui wrote:Yes, I do appreciate the power of D, I just want it to be BETTER.It'd really nice if this just works,That's clear that you've never been stuck in the fat mud of imperative and OO programming styles. You don't realize (anymore ?) how lucky we are with D templates, compared to other languages! Maybe you come from C++, so that's not so obvious for you but with my background I'm still amused when I see people complaining about such details. ^^Anyway, you can open a enhancement request and pray...I'll do that, but I just want to see some feedback on this idea....
May 05 2016
On Thursday, 5 May 2016 at 23:33:07 UTC, Yuxuan Shui wrote:On Thursday, 5 May 2016 at 23:19:59 UTC, Yuxuan Shui wrote:Wait, I just realized that this example works in 2.071, but not in 2.068.2. What has changed?On Thursday, 5 May 2016 at 23:12:40 UTC, Ed wrote:See this example: int a(alias f)(){return f(3);} int b(int z, T)(T c){return c;} void main() { a!(b!1)(); } It'd really nice if this just works, or if there's something called Curry which I can use like this: a!(Curry!(b, 1))On Thursday, 5 May 2016 at 22:53:01 UTC, Yuxuan Shui wrote:As you can see in my first post, I know how to make this work. I just think it'd be nice if compiler can do this automatically. Anothor point is that, what if I want to use partially instantiated templates as template arguments?[...]alias aa(T) = a!(1,T); aa!ubyte(2); Your alias declaration is not correct.
May 05 2016
On Friday, 6 May 2016 at 06:18:22 UTC, Yuxuan Shui wrote:On Thursday, 5 May 2016 at 23:33:07 UTC, Yuxuan Shui wrote:Apply{Left, Right} is add in 2.071 as well, and I didn't see them mentioned in the ChangLog...On Thursday, 5 May 2016 at 23:19:59 UTC, Yuxuan Shui wrote:Wait, I just realized that this example works in 2.071, but not in 2.068.2. What has changed?[...]See this example: int a(alias f)(){return f(3);} int b(int z, T)(T c){return c;} void main() { a!(b!1)(); } It'd really nice if this just works, or if there's something called Curry which I can use like this: a!(Curry!(b, 1))
May 05 2016
On Friday, 6 May 2016 at 06:26:14 UTC, Yuxuan Shui wrote:On Friday, 6 May 2016 at 06:18:22 UTC, Yuxuan Shui wrote:Oh, sorry, that doesn't work. My mistake. And ApplyLeft doesn't work for that example either (I thought it would). Looks like it's a bit more difficult to implement Curry!() than I thought.On Thursday, 5 May 2016 at 23:33:07 UTC, Yuxuan Shui wrote:Apply{Left, Right} is add in 2.071 as well, and I didn't see them mentioned in the ChangLog...On Thursday, 5 May 2016 at 23:19:59 UTC, Yuxuan Shui wrote:Wait, I just realized that this example works in 2.071, but not in 2.068.2. What has changed?[...]See this example: int a(alias f)(){return f(3);} int b(int z, T)(T c){return c;} void main() { a!(b!1)(); } It'd really nice if this just works, or if there's something called Curry which I can use like this: a!(Curry!(b, 1))
May 05 2016
On Friday, 6 May 2016 at 06:30:27 UTC, Yuxuan Shui wrote:On Friday, 6 May 2016 at 06:26:14 UTC, Yuxuan Shui wrote:I figured it out, here is a prototype of Curry: template Curry(alias tmpl, Left...) { auto Curry(Right...)(Right r) { return tmpl!Left(r); } }On Friday, 6 May 2016 at 06:18:22 UTC, Yuxuan Shui wrote:Oh, sorry, that doesn't work. My mistake. And ApplyLeft doesn't work for that example either (I thought it would). Looks like it's a bit more difficult to implement Curry!() than I thought.On Thursday, 5 May 2016 at 23:33:07 UTC, Yuxuan Shui wrote:Apply{Left, Right} is add in 2.071 as well, and I didn't see them mentioned in the ChangLog...[...]Wait, I just realized that this example works in 2.071, but not in 2.068.2. What has changed?
May 05 2016
On Thursday, 5 May 2016 at 23:19:59 UTC, Yuxuan Shui wrote:On Thursday, 5 May 2016 at 23:12:40 UTC, Ed wrote:My bad, I didn't read carefully "or not use alias:". With alias template parameter you can pass template: ------ import std.stdio; template Foo(T,U){ T pop(){return T.max;}} alias Partial(U) = Foo!(U, string); auto bar(alias Whatever)() { alias instance = Whatever!int; return instance.pop; } void main(string[] args) { writeln(bar!(Partial)()); } ------ for example.On Thursday, 5 May 2016 at 22:53:01 UTC, Yuxuan Shui wrote:As you can see in my first post, I know how to make this work. I just think it'd be nice if compiler can do this automatically. Anothor point is that, what if I want to use partially instantiated templates as template arguments?On Thursday, 5 May 2016 at 21:54:29 UTC, Ed wrote:alias aa(T) = a!(1,T); aa!ubyte(2); Your alias declaration is not correct.On Thursday, 5 May 2016 at 20:17:08 UTC, Yuxuan Shui wrote:Simple example: int a(int b, T)(T c){return 0;} It's fine to: a!1(2); But: alias A = a!1; Would fail.[...]It's hard to help without a minimal working example (maybe something with just the body). If you mean that "alias new_parser = Comb!(a, b);" generates an error maybe that's because the correct syntax is "alias new_parser(Range) = Comb!(a, b);" ? One issue you may encounter is that template parameter deduction (that's called IFTI I think) can fail with an alias (so partially specialized template/templatized function, etc).
May 05 2016
On Thursday, 5 May 2016 at 23:38:38 UTC, Ed wrote:On Thursday, 5 May 2016 at 23:19:59 UTC, Yuxuan Shui wrote:Right, Partial!() works. I just want something more generic, like the Curry I proposed. And I still think let the compiler do it is a good idea, because this could removes special cases in template arguments deductionOn Thursday, 5 May 2016 at 23:12:40 UTC, Ed wrote:My bad, I didn't read carefully "or not use alias:". With alias template parameter you can pass template: ------ import std.stdio; template Foo(T,U){ T pop(){return T.max;}} alias Partial(U) = Foo!(U, string); auto bar(alias Whatever)() { alias instance = Whatever!int; return instance.pop; } void main(string[] args) { writeln(bar!(Partial)()); } ------On Thursday, 5 May 2016 at 22:53:01 UTC, Yuxuan Shui wrote:As you can see in my first post, I know how to make this work. I just think it'd be nice if compiler can do this automatically. Anothor point is that, what if I want to use partially instantiated templates as template arguments?[...]alias aa(T) = a!(1,T); aa!ubyte(2); Your alias declaration is not correct.
May 05 2016
On Thursday, 5 May 2016 at 20:17:08 UTC, Yuxuan Shui wrote:So I was working on a parser combinator library, where the combinators take parsers as template argument. It works well until recently I decided to change the parsers so they would take Ranges instead of just strings. The combinator used to look like: template Comb(alias parser1, alias parser2) Now it looks like template Comb(alias parser1, alias parser2, Range) And I want to have the compile deduce the Range template arguments, so I don't need to change the code that uses them. But I found out it's hard to partially instantiate templates. It's OK to do that at the call site, e.g. Comb!(a, b)(range) works without specifying the Range. But sometimes I want to alias the result parser so I can use it at multiple places, but alias new_parser = Comb!(a, b); doesn't work. I need either to define Comb differently: template Comb(alias p1, alias p2) { template Comb(Range) { or not use alias: template new_parser(alias p1, alias p2){ alias new_parser(Range) = Comb!(p1, p2, Range); //Something like this, not tested } I think it would be really nice if alias can be automatically translated to the latter one. Or maybe we can have something like template Curry(alias tmpl, Args1...) { alias Curry(Args2...) = tmpl!(Args1~Args2); //Pseudocode } in the phobos.alias can automatically introduce template arguments only for function literals: alias add = (a, b) => a + b; add has two implicit template arguments: auto sum = add(4, 3.17); deduced to int and double in the case above. Actually the alias add refers to the symbol of an automatically generated template: alias add = _add_generated; template _add_generated(T1, T2) { auto _add_generated(T1 a, T2 b) { return a + b; } } The closest thing to getting the compiler to generate something like the above template is ApplyLeft/ApplyRight from std.meta:
May 05 2016