plans for macros

janderson askme at me.com
Thu May 15 00:46:28 PDT 2008


janderson wrote:
> Steven Schveighoffer wrote:
>> I just found a very good use for macros, and I was wondering how they 
>> could be used to help in this situation.
>>
>> If I have a log object, and that log object is supposed to evaluate 
>> its arguments only if the logging level allows it, checked at runtime.
>>
>> So this is the ideal usage in the calling function:
>>
>> if(log.isEnabledAtLevel(Information))
>>   log.output(someExpensiveStringBuild());
>>
>> This is ideal because it only outputs at the appropriate level, and it 
>> only evaluates the expensive function if the log level is enabled.
>>
>> However, this is very verbose, and is prone to errors.  Many log 
>> systems use the following method:
>>
>> log.outputInformation(someExpensiveStringBuild());
>>
>> Which does the if-statement for you.  However, they warn you to write 
>> your logging code in the first form if the code to build the output is 
>> expensive to avoid building the output even when it is not output.  
>> But D has a better way:
>>
>> class Log
>> {
>> void outputInformation(lazy string x)
>> {
>>     if(isEnabledAtLevel(Information))
>>       output(x);
>> }
>> }
>>
>> Now, we can still use the second form, even when building the string 
>> is expensive.  But there are issues with this solution.  For one, lazy 
>> evaluation adds delegate functions wherever the logging is required, 
>> adding to runtime and code bloat.  Second, variadic functions would be 
>> nice for logging, especially with formatting, but the only way to do 
>> lazy variadic functions is with template tuples, so there is another 
>> lot of generated code, and is even more inefficient.
>>
>> But a macro would solve the problem quite nicely.  A macro would 
>> evaluate the if statement in the calling function, and so would 
>> prevent evaluation of the expensive string building unless necessary, 
>> AND would require no delegates to do it.
>>
>> The question I have is, when macros are implemented, can I have a 
>> 'class scoped' macro?  That is, a macro that knows what context it is 
>> supposed to be in, and is passed a 'this' pointer?  And will macros 
>> support variadic arguments?
>>
>> For example, I'd like to have a macro to output formatted log 
>> information only if the log is enabled, but I want to call it like a 
>> member function of the log.
>>
>> -Steve
>>
> 
> I'm not sure if this solves your problem.  Here's an interesting syntax 
> I discovered in 1.01 (haven't checked other versions).
> 
> void LogIt(alias func)()
> {
>   if (true)
>   {
>     printf(func());
>   }
> }
> 
> LogIt!( { char[] test = "test"; return test.ptr; } )();
> 
> LogIt!( { return "test"; } )();  //You couldn't do this.
> 
> Unfortunately I don't want to update my compiler at this time to see if 
> this would work in new versions.
> 
> I also wonder if it could be simpled by wrapping it in something else -> 
> thoughts?  Its a pretty cool technique, essentially a inlined function 
> pointer.
> 
> If alias could be replaced with the word lazy string and have D add the 
> extra sugar we'd be set.
> 
> -Joel


You but can do:

LogIt!( { return "test".ptr; } )();

As to variadic you'd have to use the old C++ way if you where going to 
use this technique as I don't think alias T... works (at least it didn't 
in 1.01) ie:

void LogIt(alias func1, alias func2)()
{
   if (true)
   {
	LogIt!(func1)();
	LogIt!(func2)();
   }
}

PS -
Yes I should probably try this on my other machine with the newer D or 
setup a alternative mapping for a newer version of D on this machine.


More information about the Digitalmars-d-learn mailing list