www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Can someone explain how mixin is implemented?

reply Matthew Ong <ongbp yahoo.com> writes:
Hi,
 From what I can see mixin in D is used in place of #define in 
C++(cool!!!). However, I do have a few question.

mixin with template does address some of this issue I supposed. That 
does allow me to define up to level of content of a class but is not 
class itself.

mixin template AType(T){ // but does not seems to allow me to inherit 
ClassC this level.
private:
    T value;
public:
    this(){...}
    void print(){...}
}

class ClassB : ClassC{ // ClassC Inheritance/Interface must only be done 
at this level?
    mixin AType!(string); // content
}

Perhaps I am missing something here. How can class level definition be 
part of the mixin?

Does mixin generate the same binary code as #define as inline code,which 
meant that same binary is repeated everywhere that macro is used?

Or does it make a linked to the in a centralized locations that allow 
binary sharing when it is the same typed T??


-- 
Matthew Ong
email: ongbp yahoo.com
May 18 2011
next sibling parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Wed, 18 May 2011 09:45:56 -0400, Matthew Ong <ongbp yahoo.com> wrote:

 Hi,
  From what I can see mixin in D is used in place of #define in  
 C++(cool!!!). However, I do have a few question.

 mixin with template does address some of this issue I supposed. That  
 does allow me to define up to level of content of a class but is not  
 class itself.

 mixin template AType(T){ // but does not seems to allow me to inherit  
 ClassC this level.
 private:
     T value;
 public:
     this(){...}
     void print(){...}
 }

 class ClassB : ClassC{ // ClassC Inheritance/Interface must only be done  
 at this level?
     mixin AType!(string); // content
 }

 Perhaps I am missing something here. How can class level definition be  
 part of the mixin?

 Does mixin generate the same binary code as #define as inline code,which  
 meant that same binary is repeated everywhere that macro is used?

There is a huge difference between #define and mixin. #define is a preprocessed macro. That means, before the compiler ever sees anything, the preprocessor blindly substitutes all the #defined symbols with their definitions. This means, you can put any text (even not-grammar-correct code) into a #define A mixin is parsed by the compiler, which means it must follow the grammar of the language. You can't arbitrarily put mixins anywhere, they must be in places where mixins can be parsed. I don't think you can mixin a base class, but you can do a string mixin to define the entire class. This is not an easy thing to do, because you'd have to write the entire class as a string of text. For instance (untested): string inheritFromC(string classname, string classbodytemp) { return "class " ~ classname ~ " : ClassC { mixin " ~ classbodytemp ~ ;}"; } mixin(inheritFromC("ClassB", "AType!string")); Note, I am *not* a mixin guru, so this might be totally bunk! But I think it works. -Steve
May 18 2011
parent reply Matthew Ong <ongbp yahoo.com> writes:
On 5/18/2011 10:46 PM, Steven Schveighoffer wrote:
 but you can do a string mixin to define the entire class.  This is not
 an easy thing to do, because you'd have to write the entire class as a
 string of text.

Seen that script import somewhere before. Perhaps others would like to help. Does mixin generate the same binary code as #define as inline code,which meant that same binary is repeated everywhere that macro is used? Or does it make a linked to the in a centralized locations that allow binary sharing when it is the same typed T?? Do you have any idea? because the results is in dll/exe I cannot really tell. But someone that knows how the compiler works should be able to. -- Matthew Ong email: ongbp yahoo.com
May 18 2011
parent reply Jacob Carlborg <doob me.com> writes:
On 2011-05-18 20:05, Jonathan M Davis wrote:
 On 5/18/2011 10:46 PM, Steven Schveighoffer wrote:
 but you can do a string mixin to define the entire class. This is not
 an easy thing to do, because you'd have to write the entire class as a
 string of text.

Thanks for the attempt and sample code. Seen that script import somewhere before. Perhaps others would like to help. Does mixin generate the same binary code as #define as inline code,which meant that same binary is repeated everywhere that macro is used? Or does it make a linked to the in a centralized locations that allow binary sharing when it is the same typed T?? Do you have any idea? because the results is in dll/exe I cannot really tell. But someone that knows how the compiler works should be able to.

First off, template mixins and string mixins are different beasts. In one case, you're mixing in a template. In the other, you're mixing in strings of code. Template mixins must be valid code even without being mixed in. String mixins have to result in valid code, but they're strings so they can hold anything. Both types of mixins, however, have to be explicitly mixed in (as opposed to the textual replacement that #defines do). In the case of template mixins, you're essentially copying and pasting code. In the case of string mixins, you're creating strings that are the code, so it's pretty much just like if you typed the code in there yourself except that the compiler is putting it in there for you instead, allowing you to use functions to generate code and save you from having to type it all. There is no linking involved in mixins. It's not shared. You're generating code and inserting it where you used the mixin statement. - Jonathan M Davis

Template mixins are not exactly like copy and paste code. * You can mixin the same template, at the same location, twice, taking different parameters * Mixed in methods doesn't overload on existing methods in the scope where the mixin is used I think all this is due to mixins being mixed-in in it's own scope. -- /Jacob Carlborg
May 18 2011
parent reply Matthew Ong <ongbp yahoo.com> writes:
On 5/19/2011 2:32 AM, Jacob Carlborg wrote:
 On 2011-05-18 20:05, Jonathan M Davis wrote:
 On 5/18/2011 10:46 PM, Steven Schveighoffer wrote:
 but you can do a string mixin to define the entire class. This is not
 an easy thing to do, because you'd have to write the entire class as a
 string of text.

Thanks for the attempt and sample code. Seen that script import somewhere before. Perhaps others would like to help. Does mixin generate the same binary code as #define as inline code,which meant that same binary is repeated everywhere that macro is used? Or does it make a linked to the in a centralized locations that allow binary sharing when it is the same typed T?? Do you have any idea? because the results is in dll/exe I cannot really tell. But someone that knows how the compiler works should be able to.

First off, template mixins and string mixins are different beasts. In one case, you're mixing in a template. In the other, you're mixing in strings of code. Template mixins must be valid code even without being mixed in. String mixins have to result in valid code, but they're strings so they can hold anything. Both types of mixins, however, have to be explicitly mixed in (as opposed to the textual replacement that #defines do). In the case of template mixins, you're essentially copying and pasting code. In the case of string mixins, you're creating strings that are the code, so it's pretty much just like if you typed the code in there yourself except that the compiler is putting it in there for you instead, allowing you to use functions to generate code and save you from having to type it all. There is no linking involved in mixins. It's not shared. You're generating code and inserting it where you used the mixin statement. - Jonathan M Davis

Template mixins are not exactly like copy and paste code. * You can mixin the same template, at the same location, twice, taking different parameters * Mixed in methods doesn't overload on existing methods in the scope where the mixin is used I think all this is due to mixins being mixed-in in it's own scope.

The last message confused me. Please clarify.
not exactly like copy and paste code.

In java using template, the same LinkedList binary is shared for both String class type and also Integer class type. LinkedList<String> list=new LinkedList<String>(); LinkedList<Integer> list=new LinkedList<Integer>(); // Can also apply for Account. LinkedList<Account> list=new LinkedList<Account>(); But there is a single LinkedList Class File(single binary). mixin template does seemed to be better than #define (uncheck by compiler directly) it can be any text. M4 is a tool exactly that purpose. -- Matthew Ong email: ongbp yahoo.com
May 19 2011
next sibling parent Matthew Ong <ongbp yahoo.com> writes:
On 5/19/2011 10:02 PM, Steven Schveighoffer wrote:
 On Thu, 19 May 2011 09:43:14 -0400, Matthew Ong <ongbp yahoo.com> wrote:

According to Jonathan, In the case of template mixins, you're essentially copying and pasting code. Yes. Liked what you said, with optimization at compiled time. I am not trying to ask D to use JVM. (Please Note, that is why I choose D and also Go for the system level programming over C++ or Java JFFI.
 Java does *not* use templates, they are generics. A generic seems like,
 but is vastly different from a template.

 A template *re-generates* the code as if you substituted the type for
 the given template parameter.

 A generic generates one object code file with a base class, and then
 simply enforces the type constraints at compile time when *using* the
 generic. Under the hood, the generic is compiled with the base class as
 the given type. It probably avoids doing any type checking at runtime as
 well (since it knows the compiler will check the type for it).

automated plumbing being done like in ActiveX.
 The huge advantages of templates over generics are:

 1. The generated type can be fully optimized (footprint and code) for
 the given type parameters.

optimization. That is a really good thing. Javac has also those feature. Please do as much optimization as D can be.
 2. You can execute different code paths depending on the parameter types.
 3. You do not have to select a common base class/interface for a group
 of types. That is, you can select any set of types that will work with
 your template. With generics, all possible types need to have a common
 base.

reduced in time where only the data type is different. I understand that Java has a JVM to do that but I believe similar thing has been also proven by ActiveX/Com+/DCom. I think they termed it Object Brokering.
 4. Boxing/unboxing is not necessary for non-object types.

 The advantage of generics are that you only have one compiled version.
 This is actually very important for bytecode-based languages such as
 Java and C#.

part of D automatically. That is proven technology in the Linux Kernel for Device Driver module.
 LinkedList<String> list=new LinkedList<String>();
 LinkedList<Integer> list=new LinkedList<Integer>();

 // Can also apply for Account.
 LinkedList<Account> list=new LinkedList<Account>();


 But there is a single LinkedList Class File(single binary).

Yes, it's a LinkedList with the type given as Object. -Steve

-- Matthew Ong email: ongbp yahoo.com
May 19 2011
prev sibling parent Jacob Carlborg <doob me.com> writes:
On 2011-05-19 15:43, Matthew Ong wrote:
 On 5/19/2011 2:32 AM, Jacob Carlborg wrote:
 Template mixins are not exactly like copy and paste code.

 * You can mixin the same template, at the same location, twice, taking
 different parameters

 * Mixed in methods doesn't overload on existing methods in the scope
 where the mixin is used

 I think all this is due to mixins being mixed-in in it's own scope.

The last message confused me. Please clarify. >not exactly like copy and paste code.

I can try to example by giving an example: template Foo (int i) { void foo () {} } class Bar { mixin Foo!(3); mixin Foo!(4); } The above code works and the two methods "foo" will not conflict. You can refer to them via the template: Foo!(3).foo; Second example: template Foo () { void foo (int i) {} } class Bar { mixin Foo; void foo () {} } If template mixins where like copy and paste the first example would result in an error. In the second example you would have two methods named "foo" overloading each other. But that's not what's happening.
 Ok...So, does it meant that the compiler share some sort of binary?

 In java using template, the same LinkedList binary is shared for both
 String class type and also Integer class type.

 LinkedList<String> list=new LinkedList<String>();
 LinkedList<Integer> list=new LinkedList<Integer>();

 // Can also apply for Account.
 LinkedList<Account> list=new LinkedList<Account>();


 But there is a single LinkedList Class File(single binary).

 mixin template does seemed to be better than #define (uncheck by
 compiler directly) it can be any text. M4 is a tool exactly that purpose.

-- /Jacob Carlborg
May 19 2011
prev sibling next sibling parent reply Jesse Phillips <jessekphillips+D gmail.com> writes:
Matthew Ong Wrote:

 Perhaps I am missing something here. How can class level definition be 
 part of the mixin?
 
 Does mixin generate the same binary code as #define as inline code,which 
 meant that same binary is repeated everywhere that macro is used?
 
 Or does it make a linked to the in a centralized locations that allow 
 binary sharing when it is the same typed T??

I can see what you're trying for and it looks like you'll need string mixins to make it happen. Mixing is similar to #define in that it does string substitution, but it is unlike #define in that valid D is required declaration and call. You'll have to modify this with string mixins (I'm surprised it compiles excluding the non-existence of ClassB): mixin template AType(alias T, U, alias V){class T : ClassC { private: U value; public: this(){} void print(){} mixin V; } } class ClassC {} mixin template btype() { void someFunction() {}; } mixin AType!("ClassB", string, btype); void main() { ClassC r = new ClassB(); }
May 18 2011
parent reply Matthew Ong <ongbp yahoo.com> writes:
On 5/19/2011 1:23 AM, Jesse Phillips wrote:
 Matthew Ong Wrote:

 Perhaps I am missing something here. How can class level definition be
 part of the mixin?

 Does mixin generate the same binary code as #define as inline code,which
 meant that same binary is repeated everywhere that macro is used?

 Or does it make a linked to the in a centralized locations that allow
 binary sharing when it is the same typed T??

I can see what you're trying for and it looks like you'll need string mixins to make it happen. Mixing is similar to #define in that it does string substitution, but it is unlike #define in that valid D is required declaration and call. You'll have to modify this with string mixins (I'm surprised it compiles excluding the non-existence of ClassB): mixin template AType(alias T, U, alias V){class T : ClassC { private: U value; public: this(){} void print(){} mixin V; } } class ClassC {} mixin template btype() { void someFunction() {}; } mixin AType!("ClassB", string, btype); void main() { ClassC r = new ClassB(); }

That is cool. Useful example like this should be within the documentation also. That helped me a lot. Now, I do not have to be concerned that the class level mixin usage class missed out the inheritance and also the implementation. This pattern is very useful for flattening the Object inheritance tree. D is cool!!! -- Matthew Ong email: ongbp yahoo.com
May 19 2011
parent Matthew Ong <ongbp yahoo.com> writes:
On 5/19/2011 9:18 PM, Matthew Ong wrote:
 On 5/19/2011 1:23 AM, Jesse Phillips wrote:
 Matthew Ong Wrote:

 Perhaps I am missing something here. How can class level definition be
 part of the mixin?

 Does mixin generate the same binary code as #define as inline code,which
 meant that same binary is repeated everywhere that macro is used?

 Or does it make a linked to the in a centralized locations that allow
 binary sharing when it is the same typed T??

I can see what you're trying for and it looks like you'll need string mixins to make it happen. Mixing is similar to #define in that it does string substitution, but it is unlike #define in that valid D is required declaration and call. You'll have to modify this with string mixins (I'm surprised it compiles excluding the non-existence of ClassB): mixin template AType(alias T, U, alias V){class T : ClassC { private: U value; public: this(){} void print(){} mixin V; } } class ClassC {} mixin template btype() { void someFunction() {}; } mixin AType!("ClassB", string, btype); void main() { ClassC r = new ClassB(); }

That is cool. Useful example like this should be within the documentation also. That helped me a lot. Now, I do not have to be concerned that the class level mixin usage class missed out the inheritance and also the implementation. This pattern is very useful for flattening the Object inheritance tree. D is cool!!!

I obtain error from: ClassC r = new ClassB(); src\main.d(27): Error: undefined identifier ClassB, did you mean class ClassC? src\main.d(27): Error: ClassB is used as a type Somehow this information is not known to the compiler.... mixin AType!("ClassB", string, btype); Please help. -- Matthew Ong email: ongbp yahoo.com
May 19 2011
prev sibling next sibling parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
 On 5/18/2011 10:46 PM, Steven Schveighoffer wrote:
 but you can do a string mixin to define the entire class. This is not
 an easy thing to do, because you'd have to write the entire class as a
 string of text.

Thanks for the attempt and sample code. Seen that script import somewhere before. Perhaps others would like to help. Does mixin generate the same binary code as #define as inline code,which meant that same binary is repeated everywhere that macro is used? Or does it make a linked to the in a centralized locations that allow binary sharing when it is the same typed T?? Do you have any idea? because the results is in dll/exe I cannot really tell. But someone that knows how the compiler works should be able to.

First off, template mixins and string mixins are different beasts. In one case, you're mixing in a template. In the other, you're mixing in strings of code. Template mixins must be valid code even without being mixed in. String mixins have to result in valid code, but they're strings so they can hold anything. Both types of mixins, however, have to be explicitly mixed in (as opposed to the textual replacement that #defines do). In the case of template mixins, you're essentially copying and pasting code. In the case of string mixins, you're creating strings that are the code, so it's pretty much just like if you typed the code in there yourself except that the compiler is putting it in there for you instead, allowing you to use functions to generate code and save you from having to type it all. There is no linking involved in mixins. It's not shared. You're generating code and inserting it where you used the mixin statement. - Jonathan M Davis
May 18 2011
prev sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Thu, 19 May 2011 09:43:14 -0400, Matthew Ong <ongbp yahoo.com> wrote:

 On 5/19/2011 2:32 AM, Jacob Carlborg wrote:
 Template mixins are not exactly like copy and paste code.

 * You can mixin the same template, at the same location, twice, taking
 different parameters

 * Mixed in methods doesn't overload on existing methods in the scope
 where the mixin is used

 I think all this is due to mixins being mixed-in in it's own scope.

The last message confused me. Please clarify. >not exactly like copy and paste code. Ok...So, does it meant that the compiler share some sort of binary? In java using template, the same LinkedList binary is shared for both String class type and also Integer class type.

Java does *not* use templates, they are generics. A generic seems like, but is vastly different from a template. A template *re-generates* the code as if you substituted the type for the given template parameter. A generic generates one object code file with a base class, and then simply enforces the type constraints at compile time when *using* the generic. Under the hood, the generic is compiled with the base class as the given type. It probably avoids doing any type checking at runtime as well (since it knows the compiler will check the type for it). The huge advantages of templates over generics are: 1. The generated type can be fully optimized (footprint and code) for the given type parameters. 2. You can execute different code paths depending on the parameter types. 3. You do not have to select a common base class/interface for a group of types. That is, you can select any set of types that will work with your template. With generics, all possible types need to have a common base. 4. Boxing/unboxing is not necessary for non-object types. The advantage of generics are that you only have one compiled version. This is actually very important for bytecode-based languages such as Java and C#.
 LinkedList<String> list=new LinkedList<String>();
 LinkedList<Integer> list=new LinkedList<Integer>();

 // Can also apply for Account.
 LinkedList<Account> list=new LinkedList<Account>();


 But there is a single LinkedList Class File(single binary).

Yes, it's a LinkedList with the type given as Object. -Steve
May 19 2011