change mixins

grauzone none at example.net
Mon Feb 15 15:46:52 PST 2010


Steven Schveighoffer wrote:
> On Sun, 14 Feb 2010 18:28:38 -0500, Andrei Alexandrescu
> <SeeWebsiteForEmail at erdani.org> wrote:
> 
>> Denis Koroskin wrote:
>>> On Mon, 15 Feb 2010 00:31:29 +0300, Walter Bright 
>>> <newshound1 at digitalmars.com> wrote:
>>>
>>>> Right now, mixins are defined and used as:
>>>>
>>>>     template foo(T) { declarations... }
>>>>
>>>>     mixin foo!(int) handle;
>>>>
>>>> The proposal is to switch it around:
>>>>
>>>>     mixin template foo(T) { declarations... }
>>>>
>>>>     foo!(int) handle;
>>>>
>>>> to follow the notion that mixin templates are very different from 
>>>> regular templates, and that should be reflected in their definition 
>>>> rather than use.
>>>>
>>>> What do you think?
>>>  I support the change, expect that I believe mixing in the mixin 
>>> template should involve the "mixin" keyword.
>> [snip previous proposal]
>>
>> The hope with the proposed change is to leverage existing mixin 
>> implementation into a solid and useful facility that could actually 
>> obviate the need for macros. I reckon there is a lot of value in the 
>> current mixin template idea, but it's just packaged the wrong way. 
>> Requiring mixin on the call side (something that many have complained 
>> about) would, in my opinion, keep the feature packaged the wrong way.
>>
>> As an example of where we want to take this, consider an interpolation 
>> facility. The expression:
>>
>> interp!"a = $a and b = $b\n"
>>
>> expands into:
>>
>> "a = ", a, " and b = ", b, "\n"
>>
>> which you can writeln, pass to text or whatnot.
> 
> could you use this to avoid lazy arguments for logging?
> 
> One of the huge uses I see for a macro is to do logging (and things like
> assert) without requiring lazy evaluation.
> 
> For example, in Tango from what I remember, logging is done like this:
> 
> log.logInfo("created object " ~ obj.toString);
> 
> where you may not want to execute obj.toString unless the info log is
> enabled.  Solving this currently in Tango is done via lazy arguments.
> However, this means making temporary functions, passing delegates, etc.
> It's much more straightforward and generates smaller code to do:
> 
> if(log.infoEnabled)
>      log.log("created object " ~ obj.toString);
> 
> This is the solution in log4j and it's plethora of clones.
> 
> A much better solution IMO is to use a macro where logInfo is a macro that
> inserts the if statement at the call site.  You can do this with mixins,
> but clearly it is not as attractive, plus since you are invariably dealing
> with strings in logging, you have to escape them when doing the mixin.  It
> would be awesome if macros can solve this problem by just making mixins
> easier to use.
> 
> i.e.
> 
> class Log
> {
>      macro logInfo(s) mixin("if(this.infoEnabled) this.log(" ~ s ~ ")");
> }

Eh.
How about

class Log
{
	void logInfo(char[] format, ...) {
		if (infoEnabled)
			std.format.doFormat(&log, _arguments, _argptr);
   	}
}

Log.logInfo("created object %s", obj);


Doesn't require new features, doesn't require lazy, doesn't require 
thousands of templates, works if Log is an interface.

Granted, even if logging is disabled, the compiler will push the 
arguments on the stack and call logInfo().



More information about the Digitalmars-d mailing list