Thread overview
Quirky mixins
May 16, 2005
mattcbro
May 19, 2005
Thomas Kuehne
May 19, 2005
Thomas Kuehne
May 16, 2005
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 19, 2005
-----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
-----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-----