www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Lazy mixins

reply "Frustrated" <Frustrated nowhere.com> writes:
mixin template A()
{
      lazy mixin(B);
      //mixin(B);
}

template B()
{
     string B() { return "void foo(double d) { foo(cast(int)d); 
}"; }
}

class C
{
     void foo(int x) { writeln("x"); }
     mixin A;  // tries to add foo to class but already 
exists(even though it is not identical)
}

without the lazy mixin in A, foo is created while the template is 
being "instantiated". Then in C, the mixin does not overload foo 
and hence does nothing(there is no foo(double) in C).

If we can "lazily" evaluate the string mixin, then it would 
work(since string mixins do not do any overload analysis).

That, or allow one to overload with mixin templates.

i.e., the class C becomes

class C
{
     void foo(int x) { writeln("x"); }
     mixin(B);  // because of lazy(which doesn't evaluate string 
mixins immediately)
}

I know it doesn't seem like much but it is. Because one can't 
simplify certain things(I can't get the this pointer under the 
hood in a string template which makes code generation difficult 
and requires extra code to get everything working).
Mar 25 2014
parent reply Philippe Sigaud <philippe.sigaud gmail.com> writes:
That's probably not the solution you want, but could you use direct
string mixins?


import std.stdio;


string B() { return `void foo(double d) { writeln("foo(double)"); }`; }

class C
{
    void foo(int x) { writeln("x"); }
    mixin(B());
}

void main() {
    auto c = new C();
    c.foo(1.3);
}
Mar 25 2014
parent reply "Frustrated" <Frustrated nowhere.com> writes:
On Tuesday, 25 March 2014 at 20:23:47 UTC, Philippe Sigaud wrote:
 That's probably not the solution you want, but could you use 
 direct
 string mixins?


 import std.stdio;


 string B() { return `void foo(double d) { 
 writeln("foo(double)"); }`; }

 class C
 {
     void foo(int x) { writeln("x"); }
     mixin(B());
 }

 void main() {
     auto c = new C();
     c.foo(1.3);
 }
No, I think I mentioned that string mixins can't get the context they are inserted in. Why would I simply wrap a string mixin around a template mixin if there wasn't some purpose that string mixins couldn't use in the first place? For example, with a template mixin you can do this mixin A; while with a string mixin you have to do mixin B!(typeof(this)); because A has the context of what it is inserted an you can use typeof(this) and it refers to the proper context. In B, there is no such context so it has to be passed requiring the user to always pass it. Hence string mixins can't do everything. The problem with template mixins is that they don't properly overload(only use the name to check, if it exists then it won't insert/overload). Hence you can't do both. Use string mixins and you got to supply the argument. Use template mixins and you can't overload properly(which makes it useless in my case). If one could evaluate the string mixin after the template mixin then it would all work. (and yes, it is the solution I want unless you can actually come up with something that solves the problem directly(both overloads properly and allows one to get the context) One can't do something like template B(T = typeof(this)) { } which would also solve the problem(but string mixins don't inherit scope so it won't work).
Mar 25 2014
next sibling parent John Stahara <john.stahara+dlang gmail.com> writes:
On Tue, 25 Mar 2014 21:17:49 +0000, Frustrated wrote:

 Hence you can't do both. Use string mixins and you got to supply the
 argument. Use template mixins and you can't overload properly(which
 makes it useless in my case). If one could evaluate the string mixin
 after the template mixin then it would all work. (and yes, it is the
 solution I want unless you can actually come up with something that
 solves the problem directly(both overloads properly and allows one to
 get the context)
)
Mar 25 2014
prev sibling parent reply Philippe Sigaud <philippe.sigaud gmail.com> writes:
 No, I think I mentioned that string mixins can't get the context they are
 inserted in. Why would I simply wrap a string mixin around a template mixin
 if there wasn't some purpose that string mixins couldn't use in the first
 place?
OK. I just preferred to ask, to be sure.
 Hence you can't do both. Use string mixins and you got to supply the
 argument. Use template mixins and you can't overload properly(which makes it
 useless in my case). If one could evaluate the string mixin after the
 template mixin then it would all work. (and yes, it is the solution I want
 unless you can actually come up with something that solves the problem
 directly(both overloads properly and allows one to get the context)

 One can't do something like

 template B(T = typeof(this))
 {

 }
Did you try using a this template parameter?
Mar 25 2014
parent "Frustrated" <Who where.com> writes:
On Wednesday, 26 March 2014 at 04:05:10 UTC, Philippe Sigaud
wrote:
 No, I think I mentioned that string mixins can't get the 
 context they are
 inserted in. Why would I simply wrap a string mixin around a 
 template mixin
 if there wasn't some purpose that string mixins couldn't use 
 in the first
 place?
OK. I just preferred to ask, to be sure.
 Hence you can't do both. Use string mixins and you got to 
 supply the
 argument. Use template mixins and you can't overload 
 properly(which makes it
 useless in my case). If one could evaluate the string mixin 
 after the
 template mixin then it would all work. (and yes, it is the 
 solution I want
 unless you can actually come up with something that solves the 
 problem
 directly(both overloads properly and allows one to get the 
 context)

 One can't do something like

 template B(T = typeof(this))
 {

 }
Did you try using a this template parameter?
doesn't work. You can't use this in string mixins. There is no context.
Mar 26 2014