www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - change mixins

reply Walter Bright <newshound1 digitalmars.com> writes:
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?
Feb 14 2010
next sibling parent "Adam D. Ruppe" <destructionator gmail.com> writes:
On Sun, Feb 14, 2010 at 01:31:29PM -0800, Walter Bright wrote:
 The proposal is to switch it around:
 
    mixin template foo(T) { declarations... }
 
    foo!(int) handle;
What about: template foo() { int a; } mixin foo!(); a = 0; ? Will the change still let you use the mixed in template without a name? It would look a little weird: struct A { foo!(); }
 What do you think?
I'm on the fence. The difference seems to me that it applies in both places - definition and use. Maybe the mixin keyword should be required in both places? -- Adam D. Ruppe http://arsdnet.net
Feb 14 2010
prev sibling next sibling parent reply Michel Fortin <michel.fortin michelf.com> writes:
On 2010-02-14 16:31:29 -0500, Walter Bright <newshound1 digitalmars.com> said:

 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?
Me likes it. :-) To me it was confusing at first that templates could be used both way. I've rarely seen a template that is meant to be and not to be mixed-in at the same time, so this will make things clearer (and also enforce) how a particular template is meant to be used. And I won't say no to reducing the clutter at the usage point. I only hope you can still use it without the 'handle' part. :-) -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Feb 14 2010
parent Walter Bright <newshound1 digitalmars.com> writes:
Michel Fortin wrote:
 I only hope you can still use it without the 'handle' part. :-)
Yes, it'll still be usable that way.
Feb 14 2010
prev sibling next sibling parent reply "Nick Sabalausky" <a a.a> writes:
"Walter Bright" <newshound1 digitalmars.com> wrote in message 
news:hl9q47$2kjr$1 digitalmars.com...
 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 don't have an opinion on template mixins, as I've never really used them, but I *definitely* want that for string mixins of both the template-generated and ctfe-generated varieties.
Feb 14 2010
parent reply BCS <none anon.com> writes:
Hello Nick,

 I *definitely* want that for string mixins of both the
 template-generated and ctfe-generated varieties.
 
Why? I don't see any reason aside from documentation to do it. -- <IXOYE><
Feb 14 2010
parent reply "Nick Sabalausky" <a a.a> writes:
"BCS" <none anon.com> wrote in message 
news:a6268ff103d38cc7ba48d6fabda news.digitalmars.com...
 Hello Nick,

 I *definitely* want that for string mixins of both the
 template-generated and ctfe-generated varieties.
Why? I don't see any reason aside from documentation to do it.
Well, for one thing, not having it forces any code using my custom-assert library to look like this crap... mixin(deferAssert!(`foo == 3 || foo > 5`, "foo is bad")); ...which understandably no one wants to touch and I *absolutely* don't blame them one bit. Compare that to this... deferAssert!(`foo == 3 || foo > 5`, "foo is bad"); ...ahhh, now I can actually see what the hell's going on!
Feb 14 2010
next sibling parent reply BCS <none anon.com> writes:
Hello Nick,

 "BCS" <none anon.com> wrote in message
 news:a6268ff103d38cc7ba48d6fabda news.digitalmars.com...
 
 Hello Nick,
 
 I *definitely* want that for string mixins of both the
 template-generated and ctfe-generated varieties.
 
Why? I don't see any reason aside from documentation to do it.
Well, for one thing, not having it forces any code using my custom-assert library to look like this crap... mixin(deferAssert!(`foo == 3 || foo > 5`, "foo is bad")); ...which understandably no one wants to touch and I *absolutely* don't blame them one bit. Compare that to this... deferAssert!(`foo == 3 || foo > 5`, "foo is bad"); ...ahhh, now I can actually see what the hell's going on!
1) I don't see a lot of difference (I see a /little/ difference), the extra mixin() doesn't get in the way of /me/ seeing what going on. 2) I'd prefer more general solution, like being able to extract the original string from a lazy parameter or pass expressions as alias: void deferAssert!(alias exp, string message) { if(!exp) // deferAssert gets instanced as a local function (or gets a hidden delegate parameter or wherever) writef("%s failed: %s\n", exp.stringof, message); } 3) anything that passes code around as strings looks like a hack (sometimes necessary) to me and has so many downside relating to tools (particularly syntax highlighters) that the mixin() gets lost in the noise. void deferAssert!(foo == 3 || foo > 5, "foo is bad"); // ...ahhh, now I can really see what the hell's going on, and so can my tools! -- <IXOYE><
Feb 14 2010
parent "Nick Sabalausky" <a a.a> writes:
"BCS" <none anon.com> wrote in message 
news:a6268ff104068cc7bdef4aa51da news.digitalmars.com...
 Hello Nick,

 "BCS" <none anon.com> wrote in message
 news:a6268ff103d38cc7ba48d6fabda news.digitalmars.com...

 Hello Nick,

 I *definitely* want that for string mixins of both the
 template-generated and ctfe-generated varieties.
Why? I don't see any reason aside from documentation to do it.
Well, for one thing, not having it forces any code using my custom-assert library to look like this crap... mixin(deferAssert!(`foo == 3 || foo > 5`, "foo is bad")); ...which understandably no one wants to touch and I *absolutely* don't blame them one bit. Compare that to this... deferAssert!(`foo == 3 || foo > 5`, "foo is bad"); ...ahhh, now I can actually see what the hell's going on!
1) I don't see a lot of difference (I see a /little/ difference), the extra mixin() doesn't get in the way of /me/ seeing what going on.
Different people, I guess.
 2) I'd prefer more general solution, like being able to extract the 
 original string from a lazy parameter or pass expressions as alias:

 void deferAssert!(alias exp, string message)
 {
     if(!exp) // deferAssert gets instanced as a local function (or gets a 
 hidden delegate parameter or wherever)
        writef("%s failed: %s\n", exp.stringof, message);
 }

 3) anything that passes code around as strings looks like a hack 
 (sometimes necessary) to me and has so many downside relating to tools 
 (particularly syntax highlighters) that the mixin() gets lost in the 
 noise.

 void deferAssert!(foo == 3 || foo > 5, "foo is bad"); // ...ahhh, now I 
 can really see what the hell's going on, and so can my tools!
Good points, although for now what we have are mixins, and switching the mixin label to the declaration-side, I suspect, is a simpler change. And as far as the tools seeing it, D2 has q{} strings.
Feb 14 2010
prev sibling next sibling parent reply retard <re tard.com.invalid> writes:
Mon, 15 Feb 2010 01:08:38 -0500, Nick Sabalausky wrote:

 "BCS" <none anon.com> wrote in message
 news:a6268ff103d38cc7ba48d6fabda news.digitalmars.com...
 Hello Nick,

 I *definitely* want that for string mixins of both the
 template-generated and ctfe-generated varieties.
Why? I don't see any reason aside from documentation to do it.
Well, for one thing, not having it forces any code using my custom-assert library to look like this crap... mixin(deferAssert!(`foo == 3 || foo > 5`, "foo is bad")); ...which understandably no one wants to touch and I *absolutely* don't blame them one bit. Compare that to this... deferAssert!(`foo == 3 || foo > 5`, "foo is bad"); ...ahhh, now I can actually see what the hell's going on!
To me it's not clear why you just can't do this with higher order functions. For instance in Scala I would just write: object MyUnitTestFramework { def deferAssert(pred: => Boolean, msg: String) { if (pred) println(msg) } } or whatever functionality you might want. Passing the predicate by name does not force evaluation yet on the call site.
Feb 15 2010
parent Lutger <lutger.blijdestijn gmail.com> writes:
retard wrote:

 Mon, 15 Feb 2010 01:08:38 -0500, Nick Sabalausky wrote:
 
 "BCS" <none anon.com> wrote in message
 news:a6268ff103d38cc7ba48d6fabda news.digitalmars.com...
 Hello Nick,

 I *definitely* want that for string mixins of both the
 template-generated and ctfe-generated varieties.
Why? I don't see any reason aside from documentation to do it.
Well, for one thing, not having it forces any code using my custom-assert library to look like this crap... mixin(deferAssert!(`foo == 3 || foo > 5`, "foo is bad")); ...which understandably no one wants to touch and I *absolutely* don't blame them one bit. Compare that to this... deferAssert!(`foo == 3 || foo > 5`, "foo is bad"); ...ahhh, now I can actually see what the hell's going on!
To me it's not clear why you just can't do this with higher order functions. For instance in Scala I would just write: object MyUnitTestFramework { def deferAssert(pred: => Boolean, msg: String) { if (pred) println(msg) } } or whatever functionality you might want. Passing the predicate by name does not force evaluation yet on the call site.
You can do the same in D of course, lambda's and closures are available after all. But with a string mixin you can print the line / file info (at least you need this for D1, in D2 there is another way) AND the source code of the expression itself. That is quite useful for unittesting. Can you do that in scala?
Feb 15 2010
prev sibling parent reply grauzone <none example.net> writes:
Nick Sabalausky wrote:
 "BCS" <none anon.com> wrote in message 
 news:a6268ff103d38cc7ba48d6fabda news.digitalmars.com...
 Hello Nick,

 I *definitely* want that for string mixins of both the
 template-generated and ctfe-generated varieties.
Why? I don't see any reason aside from documentation to do it.
Well, for one thing, not having it forces any code using my custom-assert library to look like this crap... mixin(deferAssert!(`foo == 3 || foo > 5`, "foo is bad")); ...which understandably no one wants to touch and I *absolutely* don't blame them one bit. Compare that to this... deferAssert!(`foo == 3 || foo > 5`, "foo is bad"); ...ahhh, now I can actually see what the hell's going on!
Now come on, the second one also looks ugly and confusing as hell. Sure, mixins are powerful (and sometimes I couldn't avoid using them myself), but really, I never understood what people like about writing code into STRING LITERALS. At least with the mixin you see in which context the code will be compiled (though only roughly), unlike the second line of code, which just obfuscates the code further. And the only reason why you need this for your asserts is that you want to get the location of the failing assert. That's mostly because of D's lacking backtrace abilities of D (defAssert just had to resolve the location of the previous stackframe). On the other hand, I heard D2 has an ugly trick to get the caller's location: dd ddd void defAssert(bool condition, cha^Wstring message, string file = __FILE__, int line = __LINE__); defAssert(condition, message);
Feb 15 2010
parent reply "Nick Sabalausky" <a a.a> writes:
"grauzone" <none example.net> wrote in message 
news:hlbg22$6fb$1 digitalmars.com...
 Nick Sabalausky wrote:
 "BCS" <none anon.com> wrote in message 
 news:a6268ff103d38cc7ba48d6fabda news.digitalmars.com...
 Hello Nick,

 I *definitely* want that for string mixins of both the
 template-generated and ctfe-generated varieties.
Why? I don't see any reason aside from documentation to do it.
Well, for one thing, not having it forces any code using my custom-assert library to look like this crap... mixin(deferAssert!(`foo == 3 || foo > 5`, "foo is bad")); ...which understandably no one wants to touch and I *absolutely* don't blame them one bit. Compare that to this... deferAssert!(`foo == 3 || foo > 5`, "foo is bad"); ...ahhh, now I can actually see what the hell's going on!
Now come on, the second one also looks ugly and confusing as hell. Sure, mixins are powerful (and sometimes I couldn't avoid using them myself), but really, I never understood what people like about writing code into STRING LITERALS.
I certainly agree with that, but until we get AST macros or at least some movement in that direction, this sort of thing is often the best we can do.
 At least with the mixin you see in which context the code will be compiled 
 (though only roughly), unlike the second line of code, which just 
 obfuscates the code further.
I can understand that. Not sure I agree, but I can certainly see what you mean.
 And the only reason why you need this for your asserts is that you want to 
 get the location of the failing assert. That's mostly because of D's 
 lacking backtrace abilities of D (defAssert just had to resolve the 
 location of the previous stackframe).

 On the other hand, I heard D2 has an ugly trick to get the caller's 
 location:
 dd ddd
 void defAssert(bool condition, cha^Wstring message, string file = 
 __FILE__, int line = __LINE__);

 defAssert(condition, message);
Maybe it's not clear from that code, but there's more to it than that: One of the main ideas behind that lib (aside from unittests that don't exit on the first failure), is to get detailed unittest diagnostics that are comparable to what one gets from something like JUnit/NUnit, but with something much closer to actual syntax than obfuscated crap like: Assert.AreEqual(x, y); // And it just gets worse from here... // Actual examples from NUnit's documentation Assert.That( myString, Is.EqualTo("Hello") ); Assert.That(5, Is.InstanceOfType(typeof(string))); Assert.That( 5, Is.Not.SubsetOf( iarray ) ); Unittesting frameworks have garbage fake-syntax like that so that (without making the user violate DRY and state every assert in both real code for the first param and then again in plain english in the second param), it can respond to a failure by providing detailed information like: foo.cs(17): Wrong value in variable "bar". Was 3, but expected greater than 5. Instead of: foo.cs(17): Assert failure: "Wrong value" But with D's string mixins and metaprogramming, we can get diagnostics that are nearly as good, but with syntax that differs from normal expressions in little more than just sticking a few quotes around things. Not perfect, granted, but one hell of an improvement.
Feb 15 2010
parent reply grauzone <none example.net> writes:
Nick Sabalausky wrote:
 "grauzone" <none example.net> wrote in message 
 news:hlbg22$6fb$1 digitalmars.com...
 Nick Sabalausky wrote:
 "BCS" <none anon.com> wrote in message 
 news:a6268ff103d38cc7ba48d6fabda news.digitalmars.com...
 Hello Nick,

 I *definitely* want that for string mixins of both the
 template-generated and ctfe-generated varieties.
Why? I don't see any reason aside from documentation to do it.
Well, for one thing, not having it forces any code using my custom-assert library to look like this crap... mixin(deferAssert!(`foo == 3 || foo > 5`, "foo is bad")); ...which understandably no one wants to touch and I *absolutely* don't blame them one bit. Compare that to this... deferAssert!(`foo == 3 || foo > 5`, "foo is bad"); ...ahhh, now I can actually see what the hell's going on!
Now come on, the second one also looks ugly and confusing as hell. Sure, mixins are powerful (and sometimes I couldn't avoid using them myself), but really, I never understood what people like about writing code into STRING LITERALS.
I certainly agree with that, but until we get AST macros or at least some movement in that direction, this sort of thing is often the best we can do.
You're discussing here about syntax proposals to make string mixins better readable. IMHO they should stay as ugly as they are to discourage using them. (Although Andrei is already fearless enough to use advertise string mixins as a standard way to overcome the still-too-ugly syntax and bad compiler optimizer support for passing delegates; the std.algorithm documentation still passes functions as string, and his book will probably too.) Before discussing syntax improvements, you really should solve some basic problems of string mixins: for example, solve the issue that string mixins may be compiled in a completely foreign environment, as opposed to the environment where the user wrote them. (When I understand correctly, this is the "hygienic" aspect of LISP macros.) My favorite example is still this: void helper(int x) { /+ whatever here is +/ return x; } map!"helper(a)+1"(range) Also, why should the "function" passed by the user be able to access the internals of std.algorithm? Building the function with a string is not that bad (seriously ugly but works). What I've seen from early macro proposals didn't sound that great either. But what's really needed is solving the symbol lookup problems above. D macros were supposed to be hygienic, solving this particular problem. Actually, I wouldn't be too surprised if one day, Walter announced that D won't get macros, because they tried to figure out how they should work and came to the conclusion that macros suck. That's how things work in D Land, right?
 Maybe it's not clear from that code, but there's more to it than that:
 
 One of the main ideas behind that lib (aside from unittests that don't exit 
 on the first failure), is to get detailed unittest diagnostics that are 
 comparable to what one gets from something like JUnit/NUnit, but with 
 something much closer to actual syntax than obfuscated crap like:
 
 Assert.AreEqual(x, y); // And it just gets worse from here...
 
 // Actual examples from NUnit's documentation
 Assert.That( myString, Is.EqualTo("Hello") );
 Assert.That(5, Is.InstanceOfType(typeof(string)));
 Assert.That( 5, Is.Not.SubsetOf( iarray ) );
 
 Unittesting frameworks have garbage fake-syntax like that so that (without 
 making the user violate DRY and state every assert in both real code for the 
 first param and then again in plain english in the second param), it can 
 respond to a failure by providing detailed information like:
 
 foo.cs(17): Wrong value in variable "bar". Was 3, but expected greater than 
 5.
 
 Instead of:
 
 foo.cs(17): Assert failure: "Wrong value"
OK. Though I find it ironic that good old C with its dumb text based macro processor can already do half of the job by stringifying the expression passed to the assert macro. Yeah, it can't tell you the variable values. (But how would you do this in D?) And the example about logging... sometimes it looks like people are just looking for a problem to apply their solution.
 But with D's string mixins and metaprogramming, we can get diagnostics that 
 are nearly as good, but with syntax that differs from normal expressions in 
 little more than just sticking a few quotes around things. Not perfect, 
 granted, but one hell of an improvement.
Yes, otherwise I'd vote for completely removing string mixins from the language.
Feb 16 2010
parent retard <re tard.com.invalid> writes:
Tue, 16 Feb 2010 21:08:19 +0100, grauzone wrote:

 You're discussing here about syntax proposals to make string mixins
 better readable. IMHO they should stay as ugly as they are to discourage
 using them. (Although Andrei is already fearless enough to use advertise
 string mixins as a standard way to overcome the still-too-ugly syntax
 and bad compiler optimizer support for passing delegates; the
 std.algorithm documentation still passes functions as string, and his
 book will probably too.)
 
 Before discussing syntax improvements, you really should solve some
 basic problems of string mixins: for example, solve the issue that
 string mixins may be compiled in a completely foreign environment, as
 opposed to the environment where the user wrote them. (When I understand
 correctly, this is the "hygienic" aspect of LISP macros.)
 
 My favorite example is still this:
 
 void helper(int x) { /+ whatever here is +/ return x; }
 map!"helper(a)+1"(range)
 
 Also, why should the "function" passed by the user be able to access the
 internals of std.algorithm?
Agreed, lambdas should be used instead of string macros in some cases.
 
 Building the function with a string is not that bad (seriously ugly but
 works). What I've seen from early macro proposals didn't sound that
 great either. But what's really needed is solving the symbol lookup
 problems above. D macros were supposed to be hygienic, solving this
 particular problem.
 
 Actually, I wouldn't be too surprised if one day, Walter announced that
 D won't get macros, because they tried to figure out how they should
 work and came to the conclusion that macros suck. That's how things work
 in D Land, right?
My guess is that macros are getting there eventually, but atm D design team lacks manpower and D2 release is too soon so they can't really introduce a half-broken macro system now.
Feb 16 2010
prev sibling next sibling parent reply "Denis Koroskin" <2korden gmail.com> writes:
On Mon, 15 Feb 2010 00:31:29 +0300, Walter Bright  
<newshound1 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. In fact, I have proposed exactly the same more that a year ago. Here is a quote: Usually templates and mixin templates are completely different, mixin'ing usual template or instantiating template that is intended for being mixed-in makes no sense in the majority of real cases. Moreover, I would prefer to separate these terms and so their syntax: mixin template Bar { private int value; public int getValue() { return value; } } class Foo { mixin Bar!(); } int bar = Bar!().getValue(); // Error: can't instantiate mixin template template Square(alias x) { private enum temp = x * x; public enum Square = temp; } class Test { mixin Square!(42); // Error: can't mixin non-mixin template }
Feb 14 2010
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Denis Koroskin wrote:
 On Mon, 15 Feb 2010 00:31:29 +0300, Walter Bright 
 <newshound1 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. Andrei
Feb 14 2010
next sibling parent "Denis Koroskin" <2korden gmail.com> writes:
On Mon, 15 Feb 2010 02:28:38 +0300, Andrei Alexandrescu  
<SeeWebsiteForEmail erdani.org> wrote:

 Denis Koroskin wrote:
 On Mon, 15 Feb 2010 00:31:29 +0300, Walter Bright  
 <newshound1 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. Andrei
Point taken. I agree this makes code look cleaner.
Feb 14 2010
prev sibling parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Sun, 14 Feb 2010 18:28:38 -0500, Andrei Alexandrescu
<SeeWebsiteForEmail erdani.org> wrote:

 Denis Koroskin wrote:
 On Mon, 15 Feb 2010 00:31:29 +0300, Walter Bright  
 <newshound1 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 ~ ")"); } and have the compiler take care of the "this" substitution. Obviously this isn't a fully fleshed out idea, but I think abandoning the possibility of doing macros because you found an easy way to make mixins slightly better leaves out a lot of potential uses for macros. -Steve
Feb 15 2010
parent reply grauzone <none example.net> writes:
Steven Schveighoffer wrote:
 On Sun, 14 Feb 2010 18:28:38 -0500, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> wrote:
 
 Denis Koroskin wrote:
 On Mon, 15 Feb 2010 00:31:29 +0300, Walter Bright 
 <newshound1 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().
Feb 15 2010
next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Mon, 15 Feb 2010 18:46:52 -0500, grauzone <none example.net> wrote:

 Steven Schveighoffer wrote:
 On Sun, 14 Feb 2010 18:28:38 -0500, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> wrote:

 Denis Koroskin wrote:
 On Mon, 15 Feb 2010 00:31:29 +0300, Walter Bright  
 <newshound1 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
Feb 15 2010
prev sibling parent reply retard <re tard.com.invalid> writes:
Tue, 16 Feb 2010 00:46:52 +0100, grauzone wrote:

 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().
This is a case where a JIT compiler wins. The code runs equally fast without the call at all and with logging turned off (dynamically). In languages like D, the like has to be statically turned off unless compilers have any new dynamic optimizations.
Feb 16 2010
parent reply grauzone <none example.net> writes:
retard wrote:
 Granted, even if logging is disabled, the compiler will push the
 arguments on the stack and call logInfo().
This is a case where a JIT compiler wins. The code runs equally fast without the call at all and with logging turned off (dynamically). In languages like D, the like has to be statically turned off unless compilers have any new dynamic optimizations.
Can the JIT really do this optimization? It sounds as if it'd detect that the variable never changes, and generate code with that fixed value.
Feb 16 2010
parent reply retard <re tard.com.invalid> writes:
Tue, 16 Feb 2010 21:11:32 +0100, grauzone wrote:

 retard wrote:
 Granted, even if logging is disabled, the compiler will push the
 arguments on the stack and call logInfo().
This is a case where a JIT compiler wins. The code runs equally fast without the call at all and with logging turned off (dynamically). In languages like D, the like has to be statically turned off unless compilers have any new dynamic optimizations.
Can the JIT really do this optimization? It sounds as if it'd detect that the variable never changes, and generate code with that fixed value.
It sure can recompile the code assuming that the logging policy doesn't change that often - in case it does change often switching the code might have larger overhead than testing the condition. In real life you would probably start the program with either logging on or off. With JIT compiled languages, the decision can be postponed to runtime, in D it probably has to be done on compile time and provide two binaries, if both logging and efficiency are required options. I can post a rather short test case in Java/Scala here, if you insist.
Feb 16 2010
parent grauzone <none example.net> writes:
retard wrote:
 Tue, 16 Feb 2010 21:11:32 +0100, grauzone wrote:
 
 retard wrote:
 Granted, even if logging is disabled, the compiler will push the
 arguments on the stack and call logInfo().
This is a case where a JIT compiler wins. The code runs equally fast without the call at all and with logging turned off (dynamically). In languages like D, the like has to be statically turned off unless compilers have any new dynamic optimizations.
Can the JIT really do this optimization? It sounds as if it'd detect that the variable never changes, and generate code with that fixed value.
It sure can recompile the code assuming that the logging policy doesn't change that often - in case it does change often switching the code might have larger overhead than testing the condition. In real life you would probably start the program with either logging on or off. With JIT compiled languages, the decision can be postponed to runtime, in D it
We're talking about a globally accessible runtime variable here, right? Not just a local variable that was detected to be constant. What I don't understand is: how does the VM efficiently detect, that the value never changes, and that generating code for that fixed value may be worthwhile? It is well possible in theory: the VM could just set up write barriers to detect changes to a variable, and then recompile speed critical code that uses the variable. But it had to collect statistics about all accessed variables, and then decide to recompile the code. Both collecting and analyzing statistics and recompiling code takes time, and it has to be fast enough to not slow down the program even if there are "misses" (e.g. unexpected variable writes). Other typical JIT optimizations sound easy compared to this case. I'd be really interested how this works out.
 probably has to be done on compile time and provide two binaries, if both 
 logging and efficiency are required options. I can post a rather short 
 test case in Java/Scala here, if you insist.
Feb 16 2010
prev sibling next sibling parent Michel Fortin <michel.fortin michelf.com> writes:
On 2010-02-14 16:31:29 -0500, Walter Bright <newshound1 digitalmars.com> said:

 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?
There's one thing I'd wish a lot to be able to do in a template mixin: being able to get the name of the 'handle' part from inside the template. I'm wondering, if you implement this change, could you add syntax to get that? I was thinking of "mixin.stringof", and it'd be usable like this: mixin template Value(int) { int value; void write() { writeln("Value '", mixin.stringof, "' is ", value); } } class A { Value!int test; } A a = new A; a.hello.write(); // writes "Value 'test' is 0" -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Feb 14 2010
prev sibling next sibling parent reply Bill Baxter <wbaxter gmail.com> writes:
On Sun, Feb 14, 2010 at 1:31 PM, Walter Bright
<newshound1 digitalmars.com> wrote:
 Right now, mixins are defined and used as:

 =A0 template foo(T) { declarations... }

 =A0 mixin foo!(int) handle;

 The proposal is to switch it around:

 =A0 mixin template foo(T) { declarations... }

 =A0 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 u=
se. I have had one use for templates that are both stand-alone and mixed in -- that's collections of aliases and utility functions based on a particular type. For instance imagine you have a Mesh type and a template that teases apart the different subtypes it uses (VectorT, NormalT, floatT, VertexT, ColorT, etc). That's useful as a standalone: MeshTypes!(MyMeshT).VectorT But also mixed into some class that deals with meshes class MeshManipulator(MeshT) { mixin MeshTypes!(MeshT); ... } I also had a collection of geometry utility functions in a template (templated on the point type) which I would both use directly, and mix in to classes that did a lot of geometry. I guess that seems a little wasteful (creating instantiations of these same functions in multiple classes), but it was darn convenient. pointSegmentDistance(p,a,b) is much nicer than GeomUtils!(PointT).pointSegmentDistance(p,a,b). You can alias GeomUtils!(PointT) to something shorter, but aside from 'mixin' there's no way to import that templated namespace into another namespace. --bb
Feb 14 2010
next sibling parent reply Michel Fortin <michel.fortin michelf.com> writes:
On 2010-02-14 18:12:45 -0500, Bill Baxter <wbaxter gmail.com> said:

 That's useful as a standalone:
    MeshTypes!(MyMeshT).VectorT
 But also mixed into some class that deals with meshes
    class MeshManipulator(MeshT) {  mixin MeshTypes!(MeshT); ... }
Can't you use alias MeshTypes!(MyMeshT) this; now with D2? -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Feb 14 2010
parent Bill Baxter <wbaxter gmail.com> writes:
On Sun, Feb 14, 2010 at 3:39 PM, Michel Fortin
<michel.fortin michelf.com> wrote:
 On 2010-02-14 18:12:45 -0500, Bill Baxter <wbaxter gmail.com> said:

 That's useful as a standalone:
 =A0 MeshTypes!(MyMeshT).VectorT
 But also mixed into some class that deals with meshes
 =A0 class MeshManipulator(MeshT) { =A0mixin MeshTypes!(MeshT); ... }
Can't you use =A0 =A0 =A0 =A0alias MeshTypes!(MyMeshT) this; now with D2?
Maybe. But I was thinking that only worked for one type per class. If so, then 'alias this' is a limited resource I wouldn't generally want to waste on that. --bb
Feb 14 2010
prev sibling parent reply Walter Bright <newshound1 digitalmars.com> writes:
Bill Baxter wrote:
 I have had one use for templates that are both stand-alone and mixed
 in -- that's collections of aliases and utility functions based on a
 particular type.
You'll possibly run into a serious problem doing that. With templates, the name lookup is done in the scope of the template definition. With mixin templates, name lookup is done in the scope of the template instantiation.
Feb 14 2010
parent Bill Baxter <wbaxter gmail.com> writes:
On Sun, Feb 14, 2010 at 4:39 PM, Walter Bright
<newshound1 digitalmars.com> wrote:
 Bill Baxter wrote:
 I have had one use for templates that are both stand-alone and mixed
 in -- that's collections of aliases and utility functions based on a
 particular type.
You'll possibly run into a serious problem doing that. With templates, the name lookup is done in the scope of the template definition. With mixin templates, name lookup is done in the scope of the template instantiation.
Hmm, well it never caused a problem in my case. The contents of the templates were mostly self contained and didn't refer to much of anything from the outside world. Anyway, I'm not saying this is a must-have capability, just providing a data point that someone has actually used the functionality. If there's something super cool that can be enabled by making the change, then that probably wins. --bb
Feb 14 2010
prev sibling next sibling parent Chad J <chadjoan __spam.is.bad__gmail.com> writes:
Walter Bright 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?
This was discussed once: http://www.digitalmars.com/d/archives/digitalmars/D/learn/Template_mixins_Why_is_the_decision_to_mixin_made_at_the_call_site_17477.html At some level I am OK with this. Too me though, it is more important to be able to omit the "mixin" keyword at invocation than it is to dictate it at declaration. In fact, even that isn't so bad. I don't think mixin templates are really that much of an issue. String mixins are. The lack of being able to place D statements into the mixin templates makes them considerably less useful than string mixins. You can perform arbitrary (runtime) code with mixin templates of course, it's just that you have to spawn an enormous number of dummy declarations to make the wheels turn. For an example, see this monstrosity I made long ago: http://www.digitalmars.com/pnews/read.php?server=news.digitalmars.com&group=digitalmars.D&artnum=47471&header That may have been before string mixins. So I could see moving mixin from use to declaration. I just don't think I would care about it nearly as much as this: http://www.digitalmars.com/d/archives/digitalmars/D/Proposal_Dedicated-string-mixin_templates_functions_105748.html Note that with good string mixin syntax, we could have something like int foo = 42; string bar = "answer"; writefln("The $bar is $foo."); // Prints "The answer is 42." OR // Use this syntax if it needs to be greppable. The other usecase for that which came up recently was sql queries. I suppose my point in all of this is that you can probably make much better gains by messing with mixin syntax in a different way.
Feb 14 2010
prev sibling next sibling parent reply BCS <none anon.com> writes:
Hello Walter,

 The proposal is to switch it around:
[...]
 What do you think?
Off the cuff, I'm fine with needing the mixin on the template but don't drop it from the use end. Without the 'mixin' it's not visually distinct enough. On the other hand, your way would make this trick cleaner: http://arrayboundserror.blogspot.com/2009/03/i-just-got-free-25-speedup-in-my-code.html -- <IXOYE><
Feb 14 2010
parent reply "Nick Sabalausky" <a a.a> writes:
"BCS" <none anon.com> wrote in message 
news:a6268ff103d08cc7ba4f39a307e news.digitalmars.com...
 Hello Walter,

 The proposal is to switch it around:
[...]
 What do you think?
Off the cuff, I'm fine with needing the mixin on the template but don't drop it from the use end. Without the 'mixin' it's not visually distinct enough.
Not to be contentious, but why do you consider it important for it to be visually distinct?
Feb 14 2010
parent BCS <none anon.com> writes:
Hello Nick,

 "BCS" <none anon.com> wrote in message
 news:a6268ff103d08cc7ba4f39a307e news.digitalmars.com...
 
 Hello Walter,
 
 The proposal is to switch it around:
 
[...]
 What do you think?
 
Off the cuff, I'm fine with needing the mixin on the template but don't drop it from the use end. Without the 'mixin' it's not visually distinct enough.
Not to be contentious, but why do you consider it important for it to be visually distinct?
Given that these are imported from "somewhere" class list(T) { ... } template toMixin(T) { ... } How do I tell these apart (aside from by the names)? list!(int) intList; toMixin!(int) asInt; They do very different things and I can think of more time where I'd want to know what each is than where I'd want to hide it. -- <IXOYE><
Feb 14 2010
prev sibling next sibling parent reply sybrandy <sybrandy gmail.com> writes:
On 02/14/2010 04:31 PM, Walter Bright 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?
Personally, I like it. I wrote my first batch of code using mixins a couple weeks ago and I hate the fact you have to specify "mixin" every time you use the template. To me, this seemed very annoying, especially when I was trying to implement something in a way where depending on a compiler switch, the functionality would or would not be there. To me, the proposal makes it look more like a normal function, which means less typing and clutter in the code. Btw: I was doing this for a logging library that I was working on. As one can deduce, when you have a lot of logging statements in your code, being able to leverage a mixin to cleanly enable/disable the functionality in conjunction with a compiler switch can have an impact on performance. Casey
Feb 14 2010
parent reply BCS <none anon.com> writes:
Hello sybrandy,

 Btw: I was doing this for a logging library that I was working on.  As
 one can deduce, when you have a lot of logging statements in your
 code, being able to leverage a mixin to cleanly enable/disable the
 functionality in conjunction with a compiler switch can have an impact
 on performance.
How were you doing it that the mixin keyword got in your way? I think the following should work right now: version(WithLogging) mixin Logging!(whatever); -- <IXOYE><
Feb 14 2010
parent reply sybrandy <sybrandy gmail.com> writes:
On 02/15/2010 01:47 AM, BCS wrote:
 How were you doing it that the mixin keyword got in your way? I think
 the following should work right now:

 version(WithLogging) mixin Logging!(whatever);

 --
 <IXOYE><
That's actually the reverse of what I was doing. My template looked something like this (And forgive me if I screw up the syntax...I don't have the code in front of me): template Trace(string msg) { version (NoLogging) { } else { // Write to the log file... } } And then in the code you'd see something like this: mixin(Trace!("Msg...")); My reason for this was to not have the user add all the version statements throughout their code if they want to be able to compile a version with no logging. In my design, I also have a normal class that does the logging and the mixins are simply a wrapper around it. As for why the mixin keyword is in the way, how much would you like write the above line in your code? That's what I mean by being in the way. To me, the following code would be more user-friendly: mixin template Trace(string msg) { version (NoLogging) { } else { // Write to the log file... } } Trace!("Msg..."); Granted, it's not clear that a mixin is being used where you call Trace, but I don't think it really matters too much. Did I make that clear enough?
Feb 15 2010
parent reply BCS <none anon.com> writes:
Hello sybrandy,

[...]
 Did I make that clear enough?
OK I see what you are doing, but now I don't see why you are using mixins at all. (Unless you are doing the pass-expressions-as-strings trick but just didn't show that. As for that case, I've already pointed out why I think mixins at all is the wrong way to go.) -- <IXOYE><
Feb 15 2010
parent reply sybrandy <sybrandy gmail.com> writes:
On 02/15/2010 01:50 PM, BCS wrote:
 Hello sybrandy,

 [...]
 Did I make that clear enough?
OK I see what you are doing, but now I don't see why you are using mixins at all. (Unless you are doing the pass-expressions-as-strings trick but just didn't show that. As for that case, I've already pointed out why I think mixins at all is the wrong way to go.)
In short: I'm using mixins so that the person who's using the library doesn't have to put in version(DoLogging)... all over the place. By containing it in one location, I was trying to keep the code using the library cleaner.
Feb 15 2010
next sibling parent reply =?ISO-8859-1?Q?Pelle_M=E5nsson?= <pelle.mansson gmail.com> writes:
On 02/15/2010 10:53 PM, sybrandy wrote:
 In short: I'm using mixins so that the person who's using the library
 doesn't have to put in version(DoLogging)... all over the place.  By
 containing it in one location, I was trying to keep the code using the
 library cleaner.
void trace(string s) { version (NoTrace) { //do nothing } else { //do tracing } } trace("Stuff"); will this not work?
Feb 15 2010
parent reply sybrandy <sybrandy gmail.com> writes:
On 02/15/2010 05:37 PM, Pelle Månsson wrote:
 On 02/15/2010 10:53 PM, sybrandy wrote:
 In short: I'm using mixins so that the person who's using the library
 doesn't have to put in version(DoLogging)... all over the place. By
 containing it in one location, I was trying to keep the code using the
 library cleaner.
void trace(string s) { version (NoTrace) { //do nothing } else { //do tracing } } trace("Stuff"); will this not work?
It will work, however I was going for "if you're not logging, why have the logging code in there?" Like I said, I was going for performance and with mixins I could ensure there was no runtime overhead with instantiating the class, setting up the logger, etc. when the user turned logging off. In this version: template Trace(string msg) { version (NoLogging) { } else { // Write to the log file... } } If NoLogging is turned on, then no code to perform the logging is even added to the file. It seemed to me that this was favorable to having a bunch of empty functions laying around. Now, if DMD was smart enough to eliminate empty functions, that would be great and I wouldn't have to do this. Regardless, I'm still all for moving the "mixin" keyword to the mixin declaration vs. where it's instantiated.
Feb 16 2010
parent sybrandy <sybrandy gmail.com> writes:
On 02/16/2010 07:52 PM, sybrandy wrote:
 On 02/15/2010 05:37 PM, Pelle Månsson wrote:
 On 02/15/2010 10:53 PM, sybrandy wrote:
 In short: I'm using mixins so that the person who's using the library
 doesn't have to put in version(DoLogging)... all over the place. By
 containing it in one location, I was trying to keep the code using the
 library cleaner.
void trace(string s) { version (NoTrace) { //do nothing } else { //do tracing } } trace("Stuff"); will this not work?
It will work, however I was going for "if you're not logging, why have the logging code in there?" Like I said, I was going for performance and with mixins I could ensure there was no runtime overhead with instantiating the class, setting up the logger, etc. when the user turned logging off. In this version: template Trace(string msg) { version (NoLogging) { } else { // Write to the log file... } } If NoLogging is turned on, then no code to perform the logging is even added to the file. It seemed to me that this was favorable to having a bunch of empty functions laying around. Now, if DMD was smart enough to eliminate empty functions, that would be great and I wouldn't have to do this. Regardless, I'm still all for moving the "mixin" keyword to the mixin declaration vs. where it's instantiated.
Well, I tried out what you guys suggested and it worked perfectly. I really don't know why I thought there would still be a little overhead if I didn't use a mixin. So, thanks for the help. On a brighter note, at least I learned something new :)
Feb 16 2010
prev sibling parent BCS <none anon.com> writes:
Hello sybrandy,

 On 02/15/2010 01:50 PM, BCS wrote:
 
 Hello sybrandy,
 
 [...]
 
 Did I make that clear enough?
 
OK I see what you are doing, but now I don't see why you are using mixins at all. (Unless you are doing the pass-expressions-as-strings trick but just didn't show that. As for that case, I've already pointed out why I think mixins at all is the wrong way to go.)
In short: I'm using mixins so that the person who's using the library doesn't have to put in version(DoLogging)... all over the place. By containing it in one location, I was trying to keep the code using the library cleaner.
OK, but I'm still not seeing why you do it that way. Why not put the version(DoLogging) inside the logging function? void Trace(string msg)() { version (NoLogging) {} else { DoTrace(msg); } } or if that doesn't work for some reason: version (NoLogging) { void Trace(string msg)(){} } else { void Trace(string msg)() { DoTrace(msg); } } -- <IXOYE><
Feb 16 2010
prev sibling next sibling parent reply Jonathan M Davis <jmdavisProg gmail.com> writes:
Walter Bright 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 do like the idea of differentiating between normal templates and templates intended to be mixed in. However, I'm a bit concerned that removing the need for the mixin keyword when actually mixing it in could result in a loss of clarity - especially when it's legal to give the mixin a name. If I see foo!(int) handle; I'm going to thing that you just declared a variable of type foo!(int). I wouldn't expect it to be a mixin. And how could you tell except if the variable is used or not? And if it isn't, then it makes it look like maybe it's an unused variable. Disallowing the name would help foo!(int); (I don't know why you'd want the name in the first place), but I think that it's much clearer to have mixin foo!(int); That way I know exactly what you're doing. It costs some extra keystrokes, but I think that the additional clarity is well worth it. So, I think that making templates intended to be mixed in have to be marked with the mixin keyword is a good idea, but I think that it's a bad idea to not require the mixin keyword when actually mixing it in. - Jonathan M Davis
Feb 14 2010
parent reply BCS <none anon.com> writes:
Hello Jonathan,

 (I don't know why you'd want the name in the first place),
mixin foo!(int) asInt; mixin foo!(float) asFloat; Without the names you can't access anything.
 So, I think that making templates intended to be mixed in have to be
 marked with the mixin keyword is a good idea, but I think that it's a
 bad idea to not require the mixin keyword when actually mixing it in.
Ditto. -- <IXOYE><
Feb 14 2010
parent reply Jonathan M Davis <jmdavisProg gmail.com> writes:
BCS wrote:

 Hello Jonathan,
 
 (I don't know why you'd want the name in the first place),
mixin foo!(int) asInt; mixin foo!(float) asFloat; Without the names you can't access anything.
Well, I obviously need to read up on mixins again. I don't have any clue why you'd ever want to access them. I thought that they were just replaced with the code that they contain, and I don't know what you'd be trying to access. I'll have to go read the documentation again... - Jonathan M Davis
Feb 15 2010
parent BCS <none anon.com> writes:
Hello Jonathan,

 BCS wrote:
 
 Hello Jonathan,
 
 (I don't know why you'd want the name in the first place),
 
mixin foo!(int) asInt; mixin foo!(float) asFloat; Without the names you can't access anything.
Well, I obviously need to read up on mixins again. I don't have any clue why you'd ever want to access them. I thought that they were just replaced with the code that they contain, and I don't know what you'd be trying to access. I'll have to go read the documentation again...
Mixins (of that kind) are replaced by the contents of the template. Because templates only contain declarations, unless you access them, all you end up doing (RAII like cases aside) is adding unreferenced variables/functions/etc. -- <IXOYE><
Feb 15 2010
prev sibling next sibling parent reply Joel Anderson <ask me.com> writes:
On 2/14/2010 1:31 PM, Walter Bright 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 think this is a good idea. Particularly for string mixins.
Feb 15 2010
parent Ary Borenszweig <ary esperanto.org.ar> writes:
Joel Anderson wrote:
 On 2/14/2010 1:31 PM, Walter Bright 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 think this is a good idea. Particularly for string mixins.
But string mixins are a different thing, I don't think this change applies to them.
Feb 15 2010
prev sibling next sibling parent "Simen kjaeraas" <simen.kjaras gmail.com> writes:
Walter Bright <newshound1 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 wholeheartedly support this. As for the criticisms given by many here, one usage I have often encountered is the 'pseudo-type' - a mixin'ed template that offers behavior close to that of embedding a struct, but with better access to its context. -- Simen
Feb 15 2010
prev sibling parent reply "Simen kjaeraas" <simen.kjaras gmail.com> writes:
Walter Bright <newshound1 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 consensus was reached here? I see that instantiating mixin templates without the mixin prefix does not work. Will it in the future? -- Simen
Jun 29 2010
parent reply BCS <none anon.com> writes:
Hello Simen,

 Walter Bright <newshound1 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;
 
What consensus was reached here?
IIRC, none. -- ... <IXOYE><
Jun 29 2010
parent "Rory McGuire" <rmcguire neonova.co.za> writes:
On Tue, 29 Jun 2010 16:05:26 +0200, BCS <none anon.com> wrote:

 Hello Simen,

 Walter Bright <newshound1 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;
What consensus was reached here?
IIRC, none.
I really hope they make it optional at the usage site and compulsory at the definition site.
Jun 29 2010