www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Quirky mixins

reply mattcbro earthlink.net writes:
As a new D programmer I embarked on the design of a fairly complex 
data structure  (some new set algorithms I developed).  I ran into a fairly
steep learning curve using mixins.  I had originally wanted to reuse as much
code as possible, but I'm not sure that the complex restrictions of mixins and
to a lesser extent templates made this worthwhile.  Here are some of the
restrictions that tripped me up, that I somehow failed to extract from the
documentation.

1)  templates and hence mixins can only define declarations within their scope.
This means that 
int k = func(g) ;
is OK but
k = func(g) ;
is not, even though k is defined within the body prior to where the mixin is
instantiated.
2)  Code that is not declarative (e.g. if or switch statements) must appear
inside a function or class definition within a template.
3) template specialization can not use arguments passed into functions or class
constructors (even if the functions are called with constants that are known at
compile time)

e.g this won't work
template Foo(int bar: 1)
{

}

class Sup {
this(int special) {
Foo!(special) ;
}

}

4)  There are still a few quirks or perhaps bugs in the compiler. Consider the
following code:



template addit(int one: 1) {
double lhs = y + 1.0 ;
}

template addit(int zero: 0) {
double lhs = y + 0.0 ;
}



template Foo(int isone) {

/*
comment out the Foo function below and this
will compile
*/
bool Foo() {
return(false) ;
}
mixin addit!(isone) ;
}


int main(char[][] args)
{
double y = 0.0 ;
mixin Foo!(0) f0 ;
mixin Foo!(1) f1 ;
printf("lhs: %g\n", f0.lhs) ;
printf("lhs: %g\n", f1.lhs) ;
return(0) ;
}


The compiler returns the error:
mixintest.d(26): mixin Foo!(1) f1 Foo is not a template
mixintest.d(28): undefined identifier mixin Foo!(1) f1.lhs
mixintest.d(28): voids have no value
mixintest.d(28): void has no value

If the Foo function is commented out there is no problem.  This may be due to
some kind of interaction with the implicit template property concept.  However
this template has more than 1 member (Foo and lhs).

" I am the way and the truth and the life. No one comes to the Father except
through me." Jesus in -John 14
May 15 2005
next sibling parent Thomas Kuehne <thomas-dloop kuehne.this-is.spam.cn> writes:
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

mattcbro earthlink.net schrieb am Mon, 16 May 2005 03:05:23 +0000 (UTC):
 As a new D programmer I embarked on the design of a fairly complex 
 data structure  (some new set algorithms I developed).  I ran into a fairly
 steep learning curve using mixins.  I had originally wanted to reuse as much
 code as possible, but I'm not sure that the complex restrictions of mixins and
 to a lesser extent templates made this worthwhile.  Here are some of the
 restrictions that tripped me up, that I somehow failed to extract from the
 documentation.

 1)  templates and hence mixins can only define declarations within their scope.
 This means that 
 int k = func(g) ;
 is OK but
 k = func(g) ;
 is not, even though k is defined within the body prior to where the mixin is
 instantiated.
 2)  Code that is not declarative (e.g. if or switch statements) must appear
 inside a function or class definition within a template.

Disclamer: I don't know what kind of structure you are working with. Most of the time nested functions can do the job: template Tmpl(T){ static T diff(T a, T b){ return (a<b) ? (b-a) : (a-b); } } void blah(){ int a; mixin Tmpl!(typeof(a)); .... a = diff(a, a*2); .... }
 3) template specialization can not use arguments passed into functions or class
 constructors (even if the functions are called with constants that are known at
 compile time)

The arguments have to be "const". One could argue that the compiler could propagate the const attribute. The first rule set I came up with is quite complex and increases the time required for bug pointing by at least on magnitude. How about the following? template Tmpl(T){ T* buffer; .... } class Foo{ this(int i){ mixin Tmpl!(typeof(i)) tmpl; tmpl.buffer = &i; } } Thomas -----BEGIN PGP SIGNATURE----- iD8DBQFCjODj3w+/yD4P9tIRAlB0AKCOTBZrMfmgRzeo5pj2PZu/hbjSCwCfd5eW sx41UuX5N/Ee4mpb6hJ6amg= =SvH8 -----END PGP SIGNATURE-----
May 19 2005
prev sibling parent Thomas Kuehne <thomas-dloop kuehne.this-is.spam.cn> writes:
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

mattcbro earthlink.net schrieb am Mon, 16 May 2005 03:05:23 +0000 (UTC):
<snip>
 4)  There are still a few quirks or perhaps bugs in the compiler. Consider the
 following code:



 template addit(int one: 1) {
 double lhs = y + 1.0 ;
 }

 template addit(int zero: 0) {
 double lhs = y + 0.0 ;
 }



 template Foo(int isone) {

 /*
 comment out the Foo function below and this
 will compile
 */
 bool Foo() {
 return(false) ;
 }
 mixin addit!(isone) ;
 }


 int main(char[][] args)
 {
 double y = 0.0 ;
 mixin Foo!(0) f0 ;
 mixin Foo!(1) f1 ;
 printf("lhs: %g\n", f0.lhs) ;
 printf("lhs: %g\n", f1.lhs) ;
 return(0) ;
 }


 The compiler returns the error:
 mixintest.d(26): mixin Foo!(1) f1 Foo is not a template
 mixintest.d(28): undefined identifier mixin Foo!(1) f1.lhs
 mixintest.d(28): voids have no value
 mixintest.d(28): void has no value

 If the Foo function is commented out there is no problem.  This may be due to
 some kind of interaction with the implicit template property concept.  However
 this template has more than 1 member (Foo and lhs).

Please use the digitalmars.D.bugs group to post suspected bugs. Thomas -----BEGIN PGP SIGNATURE----- iD8DBQFCjOL33w+/yD4P9tIRAqPmAJ0RQ4p/R2yHfX6NME2yUzP2374QpACfe2Ce y5G35rbcABxg+IaOLfo8LoM= =IPgt -----END PGP SIGNATURE-----
May 19 2005