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