Thread overview | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
August 12, 2013 Parameter-less templates? | ||||
---|---|---|---|---|
| ||||
D has introduced a pretty cool tool: templates. These are basically namespaces that can be instantiated by a type/alias. Mixing with them the notion of "eponymous" allows to do some seriously cool things with them. One of the things I find strange though is that they *must* be parameterized. This limitation seems entirely artificial to me. Why not allow templates without parameters, just the same way some functions aren't parameterized. There are useful use-cases for this: * Simple creation of namespaces (as opposed to non-contructible struct/classes) * Allows creating private helpers, without polluting the rest of the module (private functions are still callable by other functions in the module). So... yeah, why don't we have this? -------- Related: I have encountered this problem, and I can't seem to work around it; *other* than non-parameterized templates. Basically, I have this pred function, we'll call it "foo". This pred function can itself be parameterized to take its own (optional) pred. This basically allows: foo(a, b) or foo!pred(a, b) This is "traditionally" solved by doing: void foo(A, B)(A a, B b); void foo(alias pred, A, B)(A a, B b); Here is the kicker though: "foo" is itself a pred. This means that I *need* to be able to pass "foo!pred" as a predicate. This does not work, as "foo!pred" is nothing: The compiler doesn't know what you are talking about, as the parameters A and B are missing. This is usually solved by a template: template foo(alias pred) { void foo(A, B)(A a, B b); } This works.... *however* the presence of the "void foo(A, B)(A a, B b);" confuses the crap out of the compiler: foo(a, b); //OK alias PRED = foo!"hello"; PRED(a, b); //OK BUT: foo!"hello"(a, b); //Error: Error: template hello.foo does not match any function template declaration. Candidates are: hello.foo(R1, R2)(R1 r1, R2 r2) hello.foo(alias pred) Error: template hello.foo(R1, R2)(R1 r1, R2 r2) cannot deduce template function from argument types !("hello")(int, int) Error: template instance foo!"hello" errors instantiating template So... how to make this work? AFAIK, non-parameterized templates should solve it. Or is it just a compiler issue? FYI: This is a problem present in Phobos. You can use: "equal!equal(RoR1, RoR2)" To compare two ranges of ranges. equal!equal gets instanciated, because the args are present to "finish" the missing R1/R2 args after pred. However, this neat trick stop there: "equal!(equal!equal)(RoRoR1, RoRoR2)" This time, this does not work, as the compiler can't resolve the predicate. I'd like to solve this. IMO "equal!equal" is one of the neatest "1-word" in D, and I want to make sure it works as one would expect it to. -------- So: Any workaround recommendations? Alternatives? Thoughts on parameter-less templates (regardless of my issue)? |
August 12, 2013 Re: Parameter-less templates? | ||||
---|---|---|---|---|
| ||||
Posted in reply to monarch_dodra | On 2013-08-12 21:03, monarch_dodra wrote: > D has introduced a pretty cool tool: templates. These are basically > namespaces that can be instantiated by a type/alias. Mixing with them > the notion of "eponymous" allows to do some seriously cool things with > them. > > One of the things I find strange though is that they *must* be > parameterized. This limitation seems entirely artificial to me. Why not > allow templates without parameters, just the same way some functions > aren't parameterized. There are useful use-cases for this: > * Simple creation of namespaces (as opposed to non-contructible > struct/classes) > * Allows creating private helpers, without polluting the rest of the > module (private functions are still callable by other functions in the > module). > > So... yeah, why don't we have this? Do you mean like: template Foo () { int a; } Unfortunately this doesn't work: Foo.a = 3; But this does: Foo!().a = 3; -- /Jacob Carlborg |
August 12, 2013 Re: Parameter-less templates? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jacob Carlborg | On Monday, 12 August 2013 at 19:58:32 UTC, Jacob Carlborg wrote:
> Do you mean like:
>
> template Foo ()
> {
> int a;
> }
>
> Unfortunately this doesn't work:
>
> Foo.a = 3;
>
> But this does:
>
> Foo!().a = 3;
class Foo
{
static int a;
}
template Foo()
{
int a = 0;
}
void main()
{
Foo.a = 0;
}
Wouldn't this be a problem if that syntax was allowed?
|
August 13, 2013 Re: Parameter-less templates? | ||||
---|---|---|---|---|
| ||||
Posted in reply to monarch_dodra | On Monday, 12 August 2013 at 19:03:41 UTC, monarch_dodra wrote:
> D has introduced a pretty cool tool: templates. These are basically namespaces that can be instantiated by a type/alias. Mixing with them the notion of "eponymous" allows to do some seriously cool things with them.
>
> One of the things I find strange though is that they *must* be parameterized.
Yes and no.
void foo()() {} is a parameter-less template.
As the construct already exists at semantic level, I guess making it available everywhere is the way to go.
|
August 13, 2013 Re: Parameter-less templates? | ||||
---|---|---|---|---|
| ||||
Posted in reply to monarch_dodra Attachments:
| 2013/8/13 monarch_dodra <monarchdodra@gmail.com> > Related: I have encountered this problem, and I can't seem to work around > it; *other* than non-parameterized templates. Basically, I have this pred > function, we'll call it "foo". This pred function can itself be > parameterized to take its own (optional) pred. This basically allows: > foo(a, b) > or > foo!pred(a, b) > > This is "traditionally" solved by doing: > void foo(A, B)(A a, B b); > void foo(alias pred, A, B)(A a, B b); > > Here is the kicker though: "foo" is itself a pred. This means that I *need* to be able to pass "foo!pred" as a predicate. This does not work, as "foo!pred" is nothing: The compiler doesn't know what you are talking about, as the parameters A and B are missing. This is usually solved by a template: > > template foo(alias pred) > { > void foo(A, B)(A a, B b); > } > > This works.... *however* the presence of the "void foo(A, B)(A a, B b);" > confuses the crap out of the compiler: > foo(a, b); //OK > alias PRED = foo!"hello"; > PRED(a, b); //OK > > BUT: > foo!"hello"(a, b); //Error: > Error: template hello.foo does not match any function template > declaration. Candidates are: > hello.foo(R1, R2)(R1 r1, R2 r2) > hello.foo(alias pred) > Error: template hello.foo(R1, R2)(R1 r1, R2 r2) cannot deduce template > function from argument types !("hello")(int, int) > Error: template instance foo!"hello" errors instantiating template > > So... how to make this work? AFAIK, non-parameterized templates should solve it. Or is it just a compiler issue? > > FYI: This is a problem present in Phobos. You can use: > "equal!equal(RoR1, RoR2)" > To compare two ranges of ranges. equal!equal gets instanciated, because > the args are present to "finish" the missing R1/R2 args after pred. > > However, this neat trick stop there: > "equal!(equal!equal)(RoRoR1, RoRoR2)" > This time, this does not work, as the compiler can't resolve the predicate. > > I'd like to solve this. IMO "equal!equal" is one of the neatest "1-word" in D, and I want to make sure it works as one would expect it to. > > -------- > > So: Any workaround recommendations? Alternatives? Thoughts on parameter-less templates (regardless of my issue)? > Maybe: http://d.puremagic.com/issues/show_bug.cgi?id=10811 Kenji Hara |
August 13, 2013 Re: Parameter-less templates? | ||||
---|---|---|---|---|
| ||||
Posted in reply to deadalnix | On Tuesday, 13 August 2013 at 01:08:01 UTC, deadalnix wrote:
> On Monday, 12 August 2013 at 19:03:41 UTC, monarch_dodra wrote:
>> D has introduced a pretty cool tool: templates. These are basically namespaces that can be instantiated by a type/alias. Mixing with them the notion of "eponymous" allows to do some seriously cool things with them.
>>
>> One of the things I find strange though is that they *must* be parameterized.
>
> Yes and no.
>
> void foo()() {} is a parameter-less template.
>
> As the construct already exists at semantic level, I guess making it available everywhere is the way to go.
I think strictly speaking, that is a "parameterless parameterized function", as opposed to a "non parameterized function".
In regards to template (I mean the actual "template"), I guess I wish we could either:
1. Allow non-parameterized templates (eg template foo {...})
2. Allow invoking a template without parameters (provided the template has 0 parameters, or default parameters), without doing "!()"
But yeah, I think I agree with you, that it should be made available everywhere.
|
August 13, 2013 Re: Parameter-less templates? | ||||
---|---|---|---|---|
| ||||
Posted in reply to monarch_dodra | On Tuesday, 13 August 2013 at 09:41:45 UTC, monarch_dodra wrote: > I think strictly speaking, that is a "parameterless parameterized function", as opposed to a "non parameterized function". > No, this is simply syntax sugar on top of eponymous template declaration. > In regards to template (I mean the actual "template"), I guess I wish we could either: > 1. Allow non-parameterized templates (eg template foo {...}) > 2. Allow invoking a template without parameters (provided the template has 0 parameters, or default parameters), without doing "!()" > Amen ! |
August 14, 2013 Re: Parameter-less templates? | ||||
---|---|---|---|---|
| ||||
Posted in reply to monarch_dodra | On Tuesday, 13 August 2013 at 09:41:45 UTC, monarch_dodra wrote:
>
> In regards to template (I mean the actual "template"), I guess I wish we could either:
> 1. Allow non-parameterized templates (eg template foo {...})
> 2. Allow invoking a template without parameters (provided the template has 0 parameters, or default parameters), without doing "!()"
I think your proposal no. 1 is good, but there's a problem with your proposal no. 2. This is current D code:
template get(int n = 1)
{
static if (n == 1) {
alias get = one;
}
else static if (n == 0) {
enum get = 0;
}
}
template one(int n)
{
enum one = 1;
}
template wrap(alias a)
{
enum wrap = a!0;
}
void main()
{
static assert(wrap!get == 0);
static assert(wrap!(get!()) == 1);
}
So, if we go with your proposal no. 2 (allow invoking a template without a parameter list), then the meaning of 'get' in:
wrap!get
...becomes ambiguous. We could be either passing an alias to 'get', or an alias to a parameterless instantiation of template 'get', i.e. get!().
|
Copyright © 1999-2021 by the D Language Foundation