plans for macros
janderson
askme at me.com
Thu May 15 08:35:40 PDT 2008
Steven Schveighoffer wrote:
> "janderson" wrote
>> 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.
>
> Why do you need a template? A template seems like a step backwards in ease
> of use. I'd rather have just a lazy parameter where calling it is as easy
> as:
>
> LogIt("test");
>
>
>>
>>> 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).
>
> mixin would probably work, but again, the syntax is not as appealing as a
> macro:
>
> log.formatInfo(...);
>
> vs
>
> mixin!(log.formatInfo, ...);
>
> (don't know if this is right, I don't use mixins a lot)
>
> -Steve
>
>
I'm not arguing against macros BTW. I do think however that templates
should beable to be written as simply as:
LogIt("test");
or at the very least
LogIt!("test");
-Joel
More information about the Digitalmars-d-learn
mailing list