Thread overview | |||||||||
---|---|---|---|---|---|---|---|---|---|
|
April 07, 2018 Function template argument deduction | ||||
---|---|---|---|---|
| ||||
I'm playing around with functional programming in D, and have run into a problem with the following code: --- list.d import std.variant: Algebraic, This, visit; import std.typecons: Tuple, tuple; struct Nil {} alias List(T) = Algebraic!( Nil, Tuple!(T, "head", This*, "tail") ); alias Cons(T) = Tuple!(T, "head", List!T*, "tail"); List!T* list(T)(T[] items...) { if (items.length == 0) return new List!T(Nil()); else return new List!T(Cons!T(items[0], list(items[1..$]))); } string list2string(T)(List!T list) { import std.stdio: write; list.visit!( (Nil _) => "nil", (Cons!T cons) => "cons(" ~ cons.head ~ ", " ~ list2string(*cons.tail) ~ ")" ); } unittest { List!int* myList = list(1, 2, 3); assert(list2string(*myList) == "cons(1, cons(2, cons(3, nil)))"); } --- The error I get is "template list.list2string cannot deduce function from argument types [...]"; i.e., the compiler can't figure out that T is supposed to be 'int'. My question is, why not? Is there anything I can do to get this to work? The compiler seems to be able to handle this sort of thing in general (e.g., it can deduce 'int' from an argument of type 'Tuple!(int, int)'), so what makes this particular case fail? |
April 07, 2018 Re: Function template argument deduction | ||||
---|---|---|---|---|
| ||||
Posted in reply to Paul Backus | On Saturday, 7 April 2018 at 05:10:05 UTC, Paul Backus wrote: > I'm playing around with functional programming in D, and have run into a problem with the following code: > > [...] I don't see the error you are talking about: https://run.dlang.io/is/XWPIc1 Are you using the latest compiler? |
April 07, 2018 Re: Function template argument deduction | ||||
---|---|---|---|---|
| ||||
Posted in reply to Uknown | On Saturday, 7 April 2018 at 05:46:07 UTC, Uknown wrote:
> I don't see the error you are talking about: https://run.dlang.io/is/XWPIc1
>
> Are you using the latest compiler?
Compile with -unittest.
And yes; I'm using DMD 2.079.0.
|
April 07, 2018 Re: Function template argument deduction | ||||
---|---|---|---|---|
| ||||
Posted in reply to Paul Backus | On Saturday, 7 April 2018 at 05:58:10 UTC, Paul Backus wrote:
> On Saturday, 7 April 2018 at 05:46:07 UTC, Uknown wrote:
>> I don't see the error you are talking about: https://run.dlang.io/is/XWPIc1
>>
>> Are you using the latest compiler?
>
> Compile with -unittest.
>
> And yes; I'm using DMD 2.079.0.
Now I feel silly. Anyway, I played around with your code. One thing I found was `cons.head` returns a `T`, which can't be appended to a string. You can fix this with `cons.head.to!string`, where `to` is from std.conv. I'm not sure why IFTI isn't deducing `T` to be `int` though. Hopefully some one else can help out here.
What I did notice though is that when
`string list2string(T)(List!T list)` was changed to
`string list2string(T)(VariantN!(16LU, Nil, Tuple!(T, "head", This*, "tail")) list)`
The compiler correctly deduce `T` to be `int`
|
April 06, 2018 Re: Function template argument deduction | ||||
---|---|---|---|---|
| ||||
Posted in reply to Uknown | On 04/06/2018 11:26 PM, Uknown wrote: > On Saturday, 7 April 2018 at 05:58:10 UTC, Paul Backus wrote: >> On Saturday, 7 April 2018 at 05:46:07 UTC, Uknown wrote: >>> I don't see the error you are talking about: >>> https://run.dlang.io/is/XWPIc1 >>> >>> Are you using the latest compiler? >> >> Compile with -unittest. >> >> And yes; I'm using DMD 2.079.0. > > Now I feel silly. Anyway, I played around with your code. One thing I > found was `cons.head` returns a `T`, which can't be appended to a > string. You can fix this with `cons.head.to!string`, where `to` is from > std.conv. I'm not sure why IFTI isn't deducing `T` to be `int` though. > Hopefully some one else can help out here. > > What I did notice though is that when > `string list2string(T)(List!T list)` was changed to > `string list2string(T)(VariantN!(16LU, Nil, Tuple!(T, "head", This*, > "tail")) list)` > The compiler correctly deduce `T` to be `int` I played with it as well by hacking the following: string list2string(L)(L list) { import std.traits : TemplateArgsOf; alias T = TemplateArgsOf!L[2][0]; // ... } I hit the same problem that you describe. (Additionally, list2string does not return anything.) Ali |
April 07, 2018 Re: Function template argument deduction | ||||
---|---|---|---|---|
| ||||
Posted in reply to Uknown | On Saturday, 7 April 2018 at 06:26:24 UTC, Uknown wrote:
> What I did notice though is that when
> `string list2string(T)(List!T list)` was changed to
> `string list2string(T)(VariantN!(16LU, Nil, Tuple!(T, "head", This*, "tail")) list)`
> The compiler correctly deduce `T` to be `int`
Interesting. Looks like this is an issue with aliases, because I get the error with this code too:
--- test.d
import std.typecons: Tuple, tuple;
alias Pair(T) = Tuple!(T, T);
void foo(T)(Pair!T p)
{
return;
}
unittest {
Pair!int x = tuple(1, 2);
foo(x);
}
---
|
April 07, 2018 Re: Function template argument deduction | ||||
---|---|---|---|---|
| ||||
Posted in reply to Paul Backus | On Saturday, 7 April 2018 at 14:02:55 UTC, Paul Backus wrote: > Interesting. Looks like this is an issue with aliases, because I get the error with this code too: > > --- test.d > import std.typecons: Tuple, tuple; > > alias Pair(T) = Tuple!(T, T); > > void foo(T)(Pair!T p) > { > return; > } > > unittest { > Pair!int x = tuple(1, 2); > foo(x); > } > --- Looks like this is the same problem described in issue 1807: https://issues.dlang.org/show_bug.cgi?id=1807 I'm not sure what D was like when Martin Nowak made the most recent comment on that issue, in 2012, but alias templates do have their own dedicated language construct now, so maybe this is worth revisiting. |
Copyright © 1999-2021 by the D Language Foundation