www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Using template mixin, with or without mixin ?

reply biocyberman <biocyberman gmail.com> writes:
I want to use mixin to generate function in-place. In template 
declaration, I can see 'mixin' keyword is optional. Is it true? 
What is the difference and when I must use one way over another?

This is my program:

// This works with and without 'mixin' attribute.
mixin template funcgen(T, U){

   T func1(string pr2){
     writeln("Func1: ", pr2);
   }
   U func2(string pr3){
     writeln("Func2: ", pr3);
   }

}

int main(string[] args){

   mixin funcgen!(void, void);
   func1("func1");
   func2("func2");
   return 0;

}
Apr 07 2017
parent reply =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 04/07/2017 04:47 PM, biocyberman wrote:
 I want to use mixin to generate function in-place. In template
 declaration, I can see 'mixin' keyword is optional. Is it true? What is
 the difference and when I must use one way over another?

 This is my program:

 // This works with and without 'mixin' attribute.
 mixin template funcgen(T, U){

   T func1(string pr2){
     writeln("Func1: ", pr2);
   }
   U func2(string pr3){
     writeln("Func2: ", pr3);
   }

 }

 int main(string[] args){

   mixin funcgen!(void, void);
   func1("func1");
   func2("func2");
   return 0;

 }
The difference is that you can't use funcgen as a regular template: funcgen!(void, void); Error: template instance funcgen!(void, void) mixin templates are not regular templates I think it's good practice to use 'mixin template' if it's intended to be so. Ali
Apr 07 2017
parent reply biocyberman <biocyberman gmail.com> writes:
On Friday, 7 April 2017 at 23:53:12 UTC, Ali Çehreli wrote:
 The difference is that you can't use funcgen as a regular 
 template:

     funcgen!(void, void);

 Error: template instance funcgen!(void, void) mixin templates 
 are not regular templates

 I think it's good practice to use 'mixin template' if it's 
 intended to be so.

 Ali
Thanks for a very concise answer.
Apr 08 2017
parent reply Meta <jared771 gmail.com> writes:
On Saturday, 8 April 2017 at 09:47:07 UTC, biocyberman wrote:
 On Friday, 7 April 2017 at 23:53:12 UTC, Ali Çehreli wrote:
 The difference is that you can't use funcgen as a regular 
 template:

     funcgen!(void, void);

 Error: template instance funcgen!(void, void) mixin templates 
 are not regular templates

 I think it's good practice to use 'mixin template' if it's 
 intended to be so.

 Ali
Thanks for a very concise answer.
In addition to Ali's answer, mixin templates do their symbol looking at the instantiation site, while regular templates do it at the declaration site. Example: enum a = 0; template test1() { enum b1 = a; //Okay, a is in scope at the declaration site //enum c = d1; Error: undefined identifier d1 } mixin template test2() { enum b2 = a; //Okay, a is in scope at the declaration site enum c = d1; //Okay, d1 is in scope at the *instantiation* site //enum e = d2; Error: undefined identifier d2 } void main() { enum d1 = 0; //<--d1 is declared here mixin test1!(); mixin test2!(); //<--so it is in scope here enum d2 = 0; //d2 was not declared before test2 was mixed in //so it is not in scope for test2 }
Apr 08 2017
parent reply ag0aep6g <anonymous example.com> writes:
On 04/08/2017 11:59 PM, Meta wrote:
 enum a = 0;

 template test1()
 {
     enum b1 = a; //Okay, a is in scope at the declaration site
     //enum c = d1; Error: undefined identifier d1
This line works just fine, actually. There's really no difference between a normal template and a mixin template when you use it in a mixin.
 }

 mixin template test2()
 {
     enum b2 = a; //Okay, a is in scope at the declaration site
     enum c = d1; //Okay, d1 is in scope at the *instantiation* site
     //enum e = d2; Error: undefined identifier d2
 }

 void main()
 {
     enum d1 = 0; //<--d1 is declared here
     mixin test1!();
     mixin test2!(); //<--so it is in scope here
     enum d2 = 0; //d2 was not declared before test2 was mixed in
                      //so it is not in scope for test2
 }
Apr 08 2017
parent reply Meta <jared771 gmail.com> writes:
On Saturday, 8 April 2017 at 22:37:18 UTC, ag0aep6g wrote:
 On 04/08/2017 11:59 PM, Meta wrote:
 enum a = 0;

 template test1()
 {
     enum b1 = a; //Okay, a is in scope at the declaration site
     //enum c = d1; Error: undefined identifier d1
This line works just fine, actually. There's really no difference between a normal template and a mixin template when you use it in a mixin.
 }

 mixin template test2()
 {
     enum b2 = a; //Okay, a is in scope at the declaration site
     enum c = d1; //Okay, d1 is in scope at the *instantiation* 
 site
     //enum e = d2; Error: undefined identifier d2
 }

 void main()
 {
     enum d1 = 0; //<--d1 is declared here
     mixin test1!();
     mixin test2!(); //<--so it is in scope here
     enum d2 = 0; //d2 was not declared before test2 was mixed 
 in
                      //so it is not in scope for test2
 }
Hmm, you're right, but this is not how it is supposed to behave according to the documentation. https://dlang.org/spec/template-mixin.html
Apr 08 2017
parent ag0aep6g <anonymous example.com> writes:
On 04/09/2017 07:44 AM, Meta wrote:
 On Saturday, 8 April 2017 at 22:37:18 UTC, ag0aep6g wrote:
[...]
 This line works just fine, actually. There's really no difference
 between a normal template and a mixin template when you use it in a
 mixin.
[...]
 Hmm, you're right, but this is not how it is supposed to behave
 according to the documentation.

 https://dlang.org/spec/template-mixin.html
The most fitting sentence I can find there is this: "Unlike a template instantiation, a template mixin's body is evaluated within the scope where the mixin appears, not where the template declaration is defined." But that doesn't compare the different kinds of declarations. It compares the invocations: "template instantiation" vs "template mixin". A "template instantiation" is, of course, something like `foo!()`. But the definition of a "template mixin" [1] may be a bit surprising. `mixin bar!()` is a "template mixin". It isn't and doesn't contain a "template instantiation". It's an independent language construct. Also note that the spec says: "The MixinTemplateName refers to a TemplateDeclaration." That is, MixinTemplateName is not restricted to refer to a TemplateMixinDeclaration. Actually, being pedantic, the spec doesn't say that you can use the name of a TemplateMixinDeclaration. Seems to be a minor oversight. PR: https://github.com/dlang/dlang.org/pull/1627 [1] https://dlang.org/spec/template-mixin.html#TemplateMixin
Apr 09 2017