change mixins

Steven Schveighoffer schveiguy at yahoo.com
Mon Feb 15 15:58:39 PST 2010


On Mon, 15 Feb 2010 18:46:52 -0500, grauzone <none at example.net> wrote:

> 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.

That solves my example, yes.  But it does not solve the generic case.  If  
toString isn't the complex/time consuming part, then the thing that is  
toString'd will still be computed.

-Steve



More information about the Digitalmars-d mailing list