digitalmars.D - Parameter-less templates?
- monarch_dodra (67/67) Aug 12 2013 D has introduced a pretty cool tool: templates. These are
- Jacob Carlborg (12/26) Aug 12 2013 Do you mean like:
- Meta (14/23) Aug 12 2013 class Foo
- deadalnix (5/11) Aug 12 2013 Yes and no.
- monarch_dodra (11/23) Aug 13 2013 I think strictly speaking, that is a "parameterless parameterized
- Kenji Hara (3/50) Aug 12 2013 Maybe: http://d.puremagic.com/issues/show_bug.cgi?id=10811
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)?
Aug 12 2013
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
Aug 12 2013
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?
Aug 12 2013
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.
Aug 12 2013
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: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.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.
Aug 13 2013
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 !
Aug 13 2013
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!().
Aug 14 2013
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
Aug 12 2013