plans for macros

janderson askme at me.com
Thu May 15 08:00:53 PDT 2008


Steven Schveighoffer wrote:
> "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.
> 
> Lazy evaluation is already supported, and already adds the extra sugar (not 
> sure if 1.01 does though).

For templates?  1.01 does support lazy for as function parameters but 
not as template parameters.


> 
> The problem I'm trying to solve is lazy evaluation of variadic arguments. 
> And in general, lazy evaluation is not as efficient as a macro would be --  
> there would be no automatic delegate generated, especially if variadic 
> arguments need a delegate per argument, which would generate n delegates.
> 
> I really think macros are the best solution to this problem, but I was 
> wondering how easy it would be to make macros look like member functions of 
> a class, and if they will support variadic arguments.
> 
> -Steve 
> 

Templates are just as efficient as macros, particularly if u use the 
mixin syntax (ie force inlining of the template function itself).

> 


More information about the Digitalmars-d-learn mailing list