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