Re: Metaprogramming work around

2012-04-17 Thread Erèbe

On Tuesday, 17 April 2012 at 12:46:28 UTC, Kenji Hara wrote:

On Tuesday, 17 April 2012 at 12:04:44 UTC, Erèbe wrote:
[snip]


There is something I still don't understand :

mixin template Foo( T... )
{
//Code here
}

mixin Foo!( "Hello", "Word" ); < Good


T is TemplateTypeParameter, and matches any kind of template 
arguments - types, values, and symbols. The both arguments 
"Hello" and "World" are values, so you can bind them with T.


http://dlang.org/template.html#TemplateTupleParameter




"mixin template Foo( A, T... )
{
//code here
}

mixin Foo!( "Hello", "Word" ); <--- Fail !
mixin Foo!( string, "Word" ); < Good



'A' is TemplateTypeParameter, and it matches only types. In the 
first instantiation of Foo, A doesn't match with the value 
"hello".
In the second instantiation, string is type, and T matches with 
it.


http://dlang.org/template.html#TemplateTypeParameter


mixin template Foo( alias A, T... )
{
//code here
}

mixin Foo!( "Hello", "world" ); <--- Good
mixin Foo!( string, "world" ); <--- Fail !

-


'alias A' is TemplateAliasParameter, and it matches both 
symbols and values.
Then A matches with the value "Hello", but doesn't with the 
type string.
(string is an aliased name of immutable(char)[], and it is 
built-in array type.)


http://dlang.org/template.html#TemplateAliasParameter

Kenji Hara



Thanks a lot Kenji Hara,
I have a better understanding of it now !




Re: Metaprogramming work around

2012-04-17 Thread Kenji Hara

On Tuesday, 17 April 2012 at 12:04:44 UTC, Erèbe wrote:
[snip]


There is something I still don't understand :

mixin template Foo( T... )
{
//Code here
}

mixin Foo!( "Hello", "Word" ); < Good


T is TemplateTypeParameter, and matches any kind of template 
arguments - types, values, and symbols. The both arguments 
"Hello" and "World" are values, so you can bind them with T.


http://dlang.org/template.html#TemplateTupleParameter




"mixin template Foo( A, T... )
{
//code here
}

mixin Foo!( "Hello", "Word" ); <--- Fail !
mixin Foo!( string, "Word" ); < Good



'A' is TemplateTypeParameter, and it matches only types. In the 
first instantiation of Foo, A doesn't match with the value 
"hello".
In the second instantiation, string is type, and T matches with 
it.


http://dlang.org/template.html#TemplateTypeParameter


mixin template Foo( alias A, T... )
{
//code here
}

mixin Foo!( "Hello", "world" ); <--- Good
mixin Foo!( string, "world" ); <--- Fail !

-


'alias A' is TemplateAliasParameter, and it matches both symbols 
and values.
Then A matches with the value "Hello", but doesn't with the type 
string.
(string is an aliased name of immutable(char)[], and it is 
built-in array type.)


http://dlang.org/template.html#TemplateAliasParameter

Kenji Hara


Re: Metaprogramming work around

2012-04-17 Thread Erèbe

On Tuesday, 17 April 2012 at 10:29:56 UTC, Kenji Hara wrote:

On Tuesday, 17 April 2012 at 08:28:45 UTC, Erèbe wrote:

Hi,

I'm working on some metaprogramming code which implement a 
Factory and generate an enum from a list of string.


So here my questions :

1) The documentation say mixin templates could take as 
TemplateParameterList
a "TemplateParameter , TemplateParameterList" but all my tried 
to instaciate this template failed lamentably.


mixin template Foo(T, R...)
{

  anotherTemplate!(T);
  Foo!(R);

}

mixin Foo!( string, string, string);

Is something wrong with variadic template and mixin, do i miss 
something ?



2) Below some code I writed and I wanted to know if you have 
some advice to improve it (Right maner to do it, TypeChecking, 
Safety, ...) <- variaidc arguments



The code is working is purpose is to create an enum of 
commands and to create a factory which returns me the command 
associated to a string.


Thanks !

===Code
import std.stdio;
import std.traits;
import std.conv;


//Use to create the enums of every commands
mixin template enumGenerator( T... )
{

   template generate( T... )
   {
   enum string value = T[0] ~ ", " ~ generate!( T[2..$] 
).value;

   }

   template generate() { enum string value = "UNKNOW"; }


   //Here the creation of the enum
   mixin("enum Command { " ~ generate!(T).value ~ "};");

}

//Generate a function which return a command in regard of a 
string

mixin template factoryGenerator( T... )
{
   template generate( T... )
   {
   enum string value = "if( cmd == \"" ~ T[1] ~ "\")"
   ~ "return Command." ~ T[0] ~ ";"
   ~ "else "
   ~ generate!(T[2..$]).value;
   }

   template generate() { enum string value = "return 
Command.UNKNOW;"; }


   //The function in question
   auto CommandFactory( string cmd )
   {
   mixin( generate!(T).value );
   }

}


mixin template IrcCommands( T... )
{

  mixin enumGenerator!( T );
  mixin factoryGenerator!( T );

}


void main()
{

  /*Command*/ /*String associated*/
  mixin IrcCommands!( "Connected","001",
  "NicknameUsed", "433",
  "Message",  "PRIVMSG",
  "UserLeaved",   "PART",
  "UserJoined",   "JOIN",
  "UserQuit", "QUIT"


 "UserQuit", "QUIT",   // lack of 
comma



  "Ping", "PING" );

  writefln( to!string(CommandFactory("001")) );


}


You can debug templates with adding static assertions in some 
where, like:


mixin template enumGenerator( T... )
{
template generate( T... )
{
static assert(T.length%2==0 && is(typeof(T[0]) : 
string));  // check
enum string value = T[0] ~ ", " ~ generate!( T[2..$] 
).value;

}
//[snip]
}

mixin template factoryGenerator( T... )
{
template generate( T... )
{
static assert(T.length%2==0 && is(typeof(T[1]) : 
string));  // check

enum string value = "if( cmd == \"" ~ T[1] ~ "\")"
~ "return Command." ~ T[0] ~ ";"
~ "else "
~ generate!(T[2..$]).value;
}
//[snip]
}

Bye.

Kenji Hara


Thanks for the comma !

The issue with static assert (in my case) is that the compiler 
blow you a full page of "template's instatiation error" before 
the message of your assert. Ok not even a page of the size of c++ 
template error, but that lead to your message be less noticeable.

While browsering the standard librairy I found this :

static if ( expression )
 //put your code here
else
  assert(false, "your message");

With this, the compiler print just one line, "your message". That 
pretty neat and readable enough for me :)


Stick in the magic pragma(msg, value); in here you won't regret 
it ;)
Another important thing to note here is that you should really 
reconsider using plain if/else if it's a production code not 
some toy to learn meta programming.
At very least try to generate switch over strings but I don't 
think any D compiler optimizes it. (but it should in future)
Real world options are binary search on string table or even 
better built-in hash table.


Thanks for pragma, it's awesome !

You guessed right, this code is just for the sake of learning 
some D meta programming. But I will try with an built-in hash 
table.




There is something I still don't understand :

mixin template Foo( T... )
{
//Code here
}

mixin Foo!( "Hello", "Word" ); < Good



mixin template Foo( A, T... )
{
//code here
}

mixin Foo!( "Hello", "Word" ); <--- Fail !
mixin Foo!( string, "Word" ); < Good


mixin template Foo( alias A, T... )
{
//code here
}

mixin Foo!( "Hello", "world" ); <--- Good

Re: Metaprogramming work around

2012-04-17 Thread Dmitry Olshansky

On 17.04.2012 12:28, "Erèbe" wrote:

Hi,

I'm working on some metaprogramming code which implement a Factory and
generate an enum from a list of string.

So here my questions :

1) The documentation say mixin templates could take as
TemplateParameterList
a "TemplateParameter , TemplateParameterList" but all my tried to
instaciate this template failed lamentably.

mixin template Foo(T, R...)
{

anotherTemplate!(T);
Foo!(R);

}

mixin Foo!( string, string, string);

Is something wrong with variadic template and mixin, do i miss something ?


2) Below some code I writed and I wanted to know if you have some advice
to improve it (Right maner to do it, TypeChecking, Safety, ...) <-
variaidc arguments


The code is working is purpose is to create an enum of commands and to
create a factory which returns me the command associated to a string.

Thanks !

===Code
import std.stdio;
import std.traits;
import std.conv;


//Use to create the enums of every commands
mixin template enumGenerator( T... )
{

template generate( T... )
{
enum string value = T[0] ~ ", " ~ generate!( T[2..$] ).value;
}

template generate() { enum string value = "UNKNOW"; }


//Here the creation of the enum
mixin("enum Command { " ~ generate!(T).value ~ "};");

}

//Generate a function which return a command in regard of a string
mixin template factoryGenerator( T... )
{
template generate( T... )
{
enum string value = "if( cmd == \"" ~ T[1] ~ "\")"
~ "return Command." ~ T[0] ~ ";"
~ "else "
~ generate!(T[2..$]).value;


Stick in the magic pragma(msg, value); in here you won't regret it ;)


}


Another important thing to note here is that you should really 
reconsider using plain if/else if it's a production code not some toy to 
learn meta programming.
At very least try to generate switch over strings but I don't think any 
D compiler optimizes it. (but it should in future)
Real world options are binary search on string table or even better 
built-in hash table.



--
Dmitry Olshansky


Re: Metaprogramming work around

2012-04-17 Thread Kenji Hara

On Tuesday, 17 April 2012 at 08:28:45 UTC, Erèbe wrote:

Hi,

I'm working on some metaprogramming code which implement a 
Factory and generate an enum from a list of string.


So here my questions :

1) The documentation say mixin templates could take as 
TemplateParameterList
a "TemplateParameter , TemplateParameterList" but all my tried 
to instaciate this template failed lamentably.


mixin template Foo(T, R...)
{

   anotherTemplate!(T);
   Foo!(R);

}

mixin Foo!( string, string, string);

Is something wrong with variadic template and mixin, do i miss 
something ?



2) Below some code I writed and I wanted to know if you have 
some advice to improve it (Right maner to do it, TypeChecking, 
Safety, ...) <- variaidc arguments



The code is working is purpose is to create an enum of commands 
and to create a factory which returns me the command associated 
to a string.


Thanks !

===Code
import std.stdio;
import std.traits;
import std.conv;


//Use to create the enums of every commands
mixin template enumGenerator( T... )
{

template generate( T... )
{
enum string value = T[0] ~ ", " ~ generate!( T[2..$] 
).value;

}

template generate() { enum string value = "UNKNOW"; }


//Here the creation of the enum
mixin("enum Command { " ~ generate!(T).value ~ "};");

}

//Generate a function which return a command in regard of a 
string

mixin template factoryGenerator( T... )
{
template generate( T... )
{
enum string value = "if( cmd == \"" ~ T[1] ~ "\")"
~ "return Command." ~ T[0] ~ ";"
~ "else "
~ generate!(T[2..$]).value;
}

template generate() { enum string value = "return 
Command.UNKNOW;"; }


//The function in question
auto CommandFactory( string cmd )
{
mixin( generate!(T).value );
}

}


mixin template IrcCommands( T... )
{

   mixin enumGenerator!( T );
   mixin factoryGenerator!( T );

}


void main()
{

   /*Command*/ /*String associated*/
   mixin IrcCommands!( "Connected","001",
   "NicknameUsed", "433",
   "Message",  "PRIVMSG",
   "UserLeaved",   "PART",
   "UserJoined",   "JOIN",
   "UserQuit", "QUIT"


 "UserQuit", "QUIT",   // lack of 
comma



   "Ping", "PING" );

   writefln( to!string(CommandFactory("001")) );


}


You can debug templates with adding static assertions in some 
where, like:


mixin template enumGenerator( T... )
{
template generate( T... )
{
static assert(T.length%2==0 && is(typeof(T[0]) : 
string));  // check
enum string value = T[0] ~ ", " ~ generate!( T[2..$] 
).value;

}
//[snip]
}

mixin template factoryGenerator( T... )
{
template generate( T... )
{
static assert(T.length%2==0 && is(typeof(T[1]) : 
string));  // check

enum string value = "if( cmd == \"" ~ T[1] ~ "\")"
~ "return Command." ~ T[0] ~ ";"
~ "else "
~ generate!(T[2..$]).value;
}
//[snip]
}

Bye.

Kenji Hara