Mixin and function template?

renoX renosky at free.fr
Thu Mar 1 16:38:47 PST 2007


Frits van Bommel a écrit :
> renoX wrote:
>> Frits van Bommel a écrit :
>> [cut]
>>> /** The input must be a format string with embedded "%d{var}"-style
>>>  *  formatting commands
>>>  */
>>> char[] sputf(char[] string) {
>>>     return "mixin(`std.string.format(` ~ Fmt!(" ~ escape(string) ~ ") 
>>> ~ `)`)";
>>> }
>>>
>>> void main(char[][] args) {
>>>     char[] ret;
>>>     int x = 2007;
>>>         ret = mixin(sputf("%d{x}"));
>>>         writefln("%s", ret);
>>> }
>>
>> The difference between your sputf and mine is that mine take a tuple
>> sputf(A...) instead of a string, is it be possible to have a function 
>> template take a tuple as an argument that is to say to have something 
>> like
>>
>> char[] sputf(A...)()
>> {
>>      return "std.string.format("~Fmt!(A) ~ ");";
>> }
>>
>> And still call it like you do above?
>> It doesn't work when I try to do this, I don't understand why..
> 
> For one thing, the ';' shouldn't be there.

Weird, the template that I had already for the 'writef equivalent' was:
template putf(A...)
{
     const char[] putf = "writef(" ~ Fmt!(A) ~ ");";
}
Here the ';' didn't create a problem, it's string that in the sputf 
template function it creates a problem..


> And the call syntax changes 
> slightly, you need to add the '!' to indicate they're template 
> parameters instead of function parameters.

Yes.

> (the function call 
> parentheses can be left off due to property syntax)

I hadn't realised that the removal of the parenthesis was due to the 
property syntax..

> Then you get this:
> ---
> import std.stdio;
> import std.string;
> 
> /** dummy Fmt!() for testing. This example assumes it accepts a
>  *  tuple and returns format() parameters in string form.
>  */
> template Fmt(A...) {
>     const char[] Fmt = `"%d", x`;
> }
> 
> char[] sputf(A...)()
> {
>      return "std.string.format(" ~ Fmt!(A) ~ ")";
> }
> 
> void main(char[][] args) {
>     char[] ret;
>     int x = 2007;
>     
>     ret = mixin(sputf!("%d{x}"));
>     
>     writefln("%s", ret);
> }
> ---
> which seems to work.

Yes, but what is a bit strange is that if x is an int variable
res = mixin(sputf!("%d",x)); fails (it works if x is a const int)
but mixin(putf!("%d",x)); works (putf being the template given above).

>>> As short as it is, it took me a while to get it that way.
>>> This is playing with meta-levels. It mixes in a string containing a 
>>> mixin expression. It used to be even worse though:
>>> At first the sputf() function was just a wrapper around an adapted 
>>> sputf!() template, but all the call() function did was return a 
>>> mixed-in expression, which was then wrapped into a string that - when 
>>> mixed in - assigned the second-level mixed-in result to a variable 
>>> passed by name.
>>> So it mixed in a string, that mixed in a template, that mixed in an 
>>> expression -- a three-level mixin. (Careful: multiple meta-levels 
>>> like that can get really confusing really quick :P)
>>
>> Yes, I find it very easy to be confused.
> 
> The above is actually much clearer in implementation. A bit less nice in 
> call syntax, but not by much.
> 
>>> Then I figured, that template mixin (sputfImpl!(), specifically the 
>>> call() member) must be inlinable ;).
>>>
>>> After adding an escape() function around the format string, the 
>>> result is what you see above: short but sweet.
>>>
>>> I hope you agree that
>>> ---
>>>     ret = mixin(sputf("%d{x}"));
>>> ---
>>> is a pretty good syntax :).
>>
>> I agree, but it's a limited one: you cannot do mixin(sputf("%d",x))
>> I wanted to syntax to be compatible with the old printf syntax..
> 
> Is the above what you were looking for?

Yes, thanks a lot.

renoX


More information about the Digitalmars-d-learn mailing list