Jump to page: 1 2
Thread overview
Mixin and function template?
Feb 28, 2007
renoX
Feb 28, 2007
Frits van Bommel
Feb 28, 2007
renoX
Mar 01, 2007
Frits van Bommel
Mar 01, 2007
renoX
Mar 01, 2007
Frits van Bommel
Mar 02, 2007
renoX
Mar 02, 2007
Frits van Bommel
Mar 02, 2007
renoX
Mar 02, 2007
renoX
Mar 01, 2007
Hasan Aljudy
Mar 01, 2007
renoX
February 28, 2007
Hello,

I have a template which contain a single function:
template sputf(A...)
{
	char[] call()
	{
		auto fd=std.c.stdio.fopen("tmp_file", "w+");
		mixin(`fwritef(fd,`~Fmt!(A)~`);`);
		std.c.stdio.fclose(fd);
		auto res = cast(char[])read("tmp_file");
		return res;
	}
}
At the call site, I have to do the following:
	mixin sputf!("%d{x}") P1;
	res = P1.call();
which is quite ugly, so I'd like to convert the code in a 'function template' but when I do this, I don't manage to call the function without failure..
Does someone knows how to do it?

Regards,
renoX
February 28, 2007
renoX wrote:
> I have a template which contain a single function:

Let's start with that code...

> template sputf(A...)
> {
> 	char[] call()
> 	{
> 		auto fd=std.c.stdio.fopen("tmp_file", "w+");

> 		mixin(`fwritef(fd,`~Fmt!(A)~`);`);	

This line is equivalent to:
		fwritef(fd, Fmt!(A));
no mixin() required.

> 		std.c.stdio.fclose(fd);
> 		auto res = cast(char[])read("tmp_file");

So basically, you're creating a temporary file, write some formatted output to it, then open it and put the contents in an allocated buffer?
Why not just:
		auto res = std.string.format(Fmt!(A));
?
That should allocate a string and fill it with with the formatted data. AFAICT it's equivalent to the above code, except the code above creates a file to do it, and so can get into trouble if multiple versions of it get run at the same time from the same directory...

> 		return res;

Also, you forgot to delete the file before returning. Unless that was intended? (I didn't think so :P)

> 	}
> }

So:
---
template sputf(A...)
{
	char[] call()
	{
		return std.string.format(Fmt!(A));
	}
}
---
should be pretty much identical to your code, except for tempfile-related issues in your version.

> At the call site, I have to do the following:
> 	mixin sputf!("%d{x}") P1;
> 	res = P1.call();
> which is quite ugly, so I'd like to convert the code in a 'function template' but when I do this, I don't manage to call the function without failure..
> Does someone knows how to do it?

Well, presumably the function needs to access (local?) variable 'x'. That means you can't avoid using some kind of mixin if you want to do this.

But I don't think the code left in the template is very ugly, so you could also just use it directly, like this:
---
import std.string;

// ... some stuff here ...

// example function using Fmt!()
char[] func(int x) {
        char[] res = format(Fmt!("%d{x}"));
	return res;
}
---
Which is probably cleaner than anything you'll get without:
a) changing format() to be compile-time executable, or
b) waiting until Walter sufficiently improves compile-time execution to allow current format() to be usable, or
c) implementing a compile-time format-like function yourself (either as a compile-time executable function or through template meta programming).
February 28, 2007
Frits van Bommel a écrit :
> renoX wrote:
>> I have a template which contain a single function:
> 
> Let's start with that code...
> 
>> template sputf(A...)
>> {
>>     char[] call()
>>     {
>>         auto fd=std.c.stdio.fopen("tmp_file", "w+");
> 
>>         mixin(`fwritef(fd,`~Fmt!(A)~`);`);   
> 
> This line is equivalent to:
>         fwritef(fd, Fmt!(A));
> no mixin() required.

In theory yes, in practice when I tried  fwritef(fd, Fmt!(A)); it didn't  work..

> 
>>         std.c.stdio.fclose(fd);
>>         auto res = cast(char[])read("tmp_file");
> 
> So basically, you're creating a temporary file, write some formatted output to it, then open it and put the contents in an allocated buffer?
> Why not just:
>         auto res = std.string.format(Fmt!(A));

Because I didn't know this function, thanks for the suggestion.
When I tried it didn't work though, unfortunately..

> That should allocate a string and fill it with with the formatted data. AFAICT it's equivalent to the above code, except the code above creates a file to do it, and so can get into trouble if multiple versions of it get run at the same time from the same directory...
> 
>>         return res;
> 
> Also, you forgot to delete the file before returning. Unless that was intended? (I didn't think so :P)

No, a small mistake.

> 
>>     }
>> }
> 
> So:
> ---
> template sputf(A...)
> {
>     char[] call()
>     {
>         return std.string.format(Fmt!(A));
>     }
> }
> ---
> should be pretty much identical to your code, except for tempfile-related issues in your version.
> 
>> At the call site, I have to do the following:
>>     mixin sputf!("%d{x}") P1;
>>     res = P1.call();
>> which is quite ugly, so I'd like to convert the code in a 'function template' but when I do this, I don't manage to call the function without failure..
>> Does someone knows how to do it?
> 
> Well, presumably the function needs to access (local?) variable 'x'. That means you can't avoid using some kind of mixin if you want to do this.

It's not the mixin that I want to get rid of (I can't) but what I'd like  is to rename the function call sputf and to have just one function call, this works for templates, but not for template function, weird..

> 
> But I don't think the code left in the template is very ugly, so you could also just use it directly, like this:
> ---
> import std.string;
> 
> // ... some stuff here ...
> 
> // example function using Fmt!()
> char[] func(int x) {
>         char[] res = format(Fmt!("%d{x}"));
>     return res;
> }
> ---
> Which is probably cleaner than anything you'll get without:
> a) changing format() to be compile-time executable, or
> b) waiting until Walter sufficiently improves compile-time execution to allow current format() to be usable, or
> c) implementing a compile-time format-like function yourself (either as a compile-time executable function or through template meta programming).

Fmt! is doing c), it is limitated of course because I choose not to parse a string and templates do not accept expressions..

The fact that format is not working, nor fwrite(fd but mixin(fwrite(fd works make me thing of a bug..

renoX
March 01, 2007
renoX wrote:
> Frits van Bommel a écrit :
>> renoX wrote:
>>>         mixin(`fwritef(fd,`~Fmt!(A)~`);`);   
>>
>> This line is equivalent to:
>>         fwritef(fd, Fmt!(A));
>  > no mixin() required.
> 
> In theory yes, in practice when I tried  fwritef(fd, Fmt!(A)); it didn't  work..

Oh, sorry. I should have seen that Fmt!() generates the arguments as a string, not a tuple. So you'd still need the mixin wrapper here.

>>>         std.c.stdio.fclose(fd);
>>>         auto res = cast(char[])read("tmp_file");
>>
>> So basically, you're creating a temporary file, write some formatted output to it, then open it and put the contents in an allocated buffer?
>> Why not just:
>>         auto res = std.string.format(Fmt!(A));
> 
> Because I didn't know this function, thanks for the suggestion.
> When I tried it didn't work though, unfortunately..

This should be equivalent to your original[1]:
	auto res = mixin("std.string.format(" ~ Fmt!(A) ~ ")");


[1]: Of course, my previous suggestion *should* have been equivalent as well. Unfortunately it wasn't ;).

>>> At the call site, I have to do the following:
>>>     mixin sputf!("%d{x}") P1;
>>>     res = P1.call();
>>> which is quite ugly, so I'd like to convert the code in a 'function template' but when I do this, I don't manage to call the function without failure..
>>> Does someone knows how to do it?
>>
>> Well, presumably the function needs to access (local?) variable 'x'. That means you can't avoid using some kind of mixin if you want to do this.
> 
> It's not the mixin that I want to get rid of (I can't) but what I'd like  is to rename the function call sputf and to have just one function call, this works for templates, but not for template function, weird..

You could have a compile-time function generate a string that calls the appropriate code.

Here's what I came up with:
---
import std.stdio;
import std.string;

/** dummy Fmt!() for testing. This example assumes it accepts a
 *  single string and returns format() parameters in string form.
 */
template Fmt(char[] A) {
	const char[] Fmt = `"%d", x`;
}

/** Ensures escape codes and quotes in strings are escaped themselves.
 *  Not thoroughly checked, but the idea is that the following should
 *  hold for all strings:
 *  ---
 *      string == mixin(escape(string));
 *  ---
 */
char[] escape(char[] string) {
	char[] result = "\"";
	foreach (c; string) {
		if (c == '\\')
			result ~= "\\\\";
		else if (c == '"')
			result ~= "\\\"";
		else
			result ~= c;
	}
	result ~= "\"";
	return result;
}

/** 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);
}
---

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)

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 :).
March 01, 2007

renoX wrote:
> Hello,
> 
> I have a template which contain a single function:
> template sputf(A...)
> {
> 	char[] call()
> 	{
> 		auto fd=std.c.stdio.fopen("tmp_file", "w+");
> 		mixin(`fwritef(fd,`~Fmt!(A)~`);`);	
> 		std.c.stdio.fclose(fd);
> 		auto res = cast(char[])read("tmp_file");
> 		return res;
> 	}
> }
> At the call site, I have to do the following:
> 	mixin sputf!("%d{x}") P1;
> 	res = P1.call();
> which is quite ugly, so I'd like to convert the code in a 'function template' but when I do this, I don't manage to call the function without failure..
> Does someone knows how to do it?
> 
> Regards,
> renoX


I wrote some code so that you could print local variables or expressions by wrapping them with {{ double braces }} inside the string (this is a Django idiom).

The code is not so stable as it doesn't do anything about escaping and stuff .. and it's not really tested at all .. except for one use-case;
it's the intended typical usage:

auto name = "hasan";
mixin( bang( "hello {{name}}, how are you?" ) );

the idea is to replace bang("string1 {{expr}} string2") with
writefln( "string1", expr, "string2" );

Here's the code, it's written in an ugly aggressive way because it was my first attempt to play with mixins & compile-time functions, so I stayed as low-level as possible.
------------
import std.stdio;

char[] parse( char[] string )
{
    char[] result = "";
    int index = 0;
    while( index < string.length )
    {
        //scan for {{
        bool sequence = false;
        int start = index;
        while(index < string.length)
        {
            if( (index < string.length-2) )
            {
                if( (string[index] == '{') && (string[index+1] == '{') )
                {
                    sequence = true;
                    break;
                }
            }
            index++;
        }
        auto raw = string[start..index]; //this holds the contents of string up to the first "{{" if there is one.

        if( result.length > 0 )
            result = result ~ ", ";
        result = result ~ `"` ~ raw ~ `"`;

        if( sequence )
        {
            index+= 2;
            start = index;
            //look for }}
            while( (index < string.length-2) )
            {
                if( (string[index] == '}') && (string[index+1] == '}') )
                    break;
                index++;
            }
            auto exp = string[start..index];
            result = result ~ ", " ~ exp;
            index += 2;
        }
    }

    return result;
}

char[] bang( char[] expr )
{
    expr = parse(expr);
    return `writefln(` ~ expr ~ `);`;
}

void main()
{
    auto name = "hasan";
    mixin( bang( "hello {{name}}, how are you?" ) );
}
----------

March 01, 2007
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..


> ---
> 
> 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.

> 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..

Regards,
renoX

March 01, 2007
Hasan Aljudy a écrit :
> 
> 
> renoX wrote:
>> Hello,
>>
>> I have a template which contain a single function:
>> template sputf(A...)
>> {
>>     char[] call()
>>     {
>>         auto fd=std.c.stdio.fopen("tmp_file", "w+");
>>         mixin(`fwritef(fd,`~Fmt!(A)~`);`);           std.c.stdio.fclose(fd);
>>         auto res = cast(char[])read("tmp_file");
>>         return res;
>>     }
>> }
>> At the call site, I have to do the following:
>>     mixin sputf!("%d{x}") P1;
>>     res = P1.call();
>> which is quite ugly, so I'd like to convert the code in a 'function template' but when I do this, I don't manage to call the function without failure..
>> Does someone knows how to do it?
>>
>> Regards,
>> renoX
> 
> 
> I wrote some code so that you could print local variables or expressions by wrapping them with {{ double braces }} inside the string (this is a Django idiom).

Thanks for your code, the syntax I used is inspired from Ruby #{} except that I thought that in printf '%' is the escape char, that's why I'm using %s{} or %d{} (and %{ as equivalent to '{')

We're doing more or less the same thing, except that my implementation takes a tuple instead of just one string which allows to be a little bit compatible with printf: mixin(putf!("%d",x)) works.

But I have a hard time making the equivalent of for format/sprintf..

renoX


> 
> The code is not so stable as it doesn't do anything about escaping and stuff .. and it's not really tested at all .. except for one use-case;
> it's the intended typical usage:
> 
> auto name = "hasan";
> mixin( bang( "hello {{name}}, how are you?" ) );
> 
> the idea is to replace bang("string1 {{expr}} string2") with
> writefln( "string1", expr, "string2" );
> 
> Here's the code, it's written in an ugly aggressive way because it was my first attempt to play with mixins & compile-time functions, so I stayed as low-level as possible.
> ------------
> import std.stdio;
> 
> char[] parse( char[] string )
> {
>     char[] result = "";
>     int index = 0;
>     while( index < string.length )
>     {
>         //scan for {{
>         bool sequence = false;
>         int start = index;
>         while(index < string.length)
>         {
>             if( (index < string.length-2) )
>             {
>                 if( (string[index] == '{') && (string[index+1] == '{') )
>                 {
>                     sequence = true;
>                     break;
>                 }
>             }
>             index++;
>         }
>         auto raw = string[start..index]; //this holds the contents of string up to the first "{{" if there is one.
> 
>         if( result.length > 0 )
>             result = result ~ ", ";
>         result = result ~ `"` ~ raw ~ `"`;
> 
>         if( sequence )
>         {
>             index+= 2;
>             start = index;
>             //look for }}
>             while( (index < string.length-2) )
>             {
>                 if( (string[index] == '}') && (string[index+1] == '}') )
>                     break;
>                 index++;
>             }
>             auto exp = string[start..index];
>             result = result ~ ", " ~ exp;
>             index += 2;
>         }
>     }
> 
>     return result;
> }
> 
> char[] bang( char[] expr )
> {
>     expr = parse(expr);
>     return `writefln(` ~ expr ~ `);`;
> }
> 
> void main()
> {
>     auto name = "hasan";
>     mixin( bang( "hello {{name}}, how are you?" ) );
> }
> ----------
> 
March 01, 2007
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. And the call syntax changes slightly, you need to add the '!' to indicate they're template parameters instead of function parameters. (the function call parentheses can be left off due to 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.

>> 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?
March 02, 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
March 02, 2007
renoX wrote:
> Frits van Bommel a écrit :
>> renoX wrote:
>>> 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..

There are three kinds of mixins[1]: mixin declarations, mixin statements and mixin expressions. Your putf string is used as a mixin statement, while the sputf string is used as a mixin expression.
See http://www.digitalmars.com/d/changelog.html#new1_005 for the spec links, but essentially mixin statements generate statements (including any terminating ';'s) while mixin expressions just generate (sub)expressions, which don't contain ';'s.


[1] excluding template mixins, which are a different beast altogether.

>> 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).

The behaviors differ? That's a bit weird...
They both use template parameters, so they should have the exact same restrictions AFAIK.

[a bit of research later]
I think this is a restriction of compile-time function evaluation.
From http://www.digitalmars.com/d/function.html#interpretation :
---
expressions in the function may not:
[snip]
    * reference any global state or variables
    * reference any local static variables
[snip]
---
Those /could/ be interpreted to disallow alias template parameter usage...

Luckily the fix is easy, just transform it to be similar to your putf template to avoid CTFE:
---
template sputf(A...)
{
     const sputf = "std.string.format(" ~ Fmt!(A) ~ ")";
}
---
works perfectly fine, even with non-constant integer variables as parameters.

And the call syntax didn't even change :).
« First   ‹ Prev
1 2