www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Recursive mixins problem

reply Max Samukha <samukha voliacable.com> writes:
Why recursive mixins are disallowed?

template Call(A...)
{
    static if (A.length > 0)
    {
        void call(A[0] fn)
        {
        }

        mixin Call!(A[1..$]);
    }
}

class Caller(A...)
{
    mixin Call!(A);
}

void main()
{
    auto caller = new Caller!(int delegate(), char[] delegate());
}

hello.d(15): mixin hello.Caller!(int delegate(),char[]
delegate()).Caller.Call!(int delegate(),char[]
delegate()).Call!(char[] delegate()).Call!() recursive mixin
instantiation
hello.d(26): template instance hello.Caller!(int delegate(),char[]
delegate()) error instantiating
Apr 07 2007
next sibling parent Max Samukha <samukha voliacable.com> writes:
On Sat, 07 Apr 2007 16:55:16 +0300, Max Samukha
<samukha voliacable.com> wrote:

Why recursive mixins are disallowed?

template Call(A...)
{
    static if (A.length > 0)
    {
        void call(A[0] fn)
        {
        }

        mixin Call!(A[1..$]);
    }
}

class Caller(A...)
{
    mixin Call!(A);
}

void main()
{
    auto caller = new Caller!(int delegate(), char[] delegate());
}

hello.d(15): mixin hello.Caller!(int delegate(),char[]
delegate()).Caller.Call!(int delegate(),char[]
delegate()).Call!(char[] delegate()).Call!() recursive mixin
instantiation
hello.d(26): template instance hello.Caller!(int delegate(),char[]
delegate()) error instantiating
In the example above, char[] delegate() should be replaced with something like int delegate(char[]) for proper function overloading. Anyway, the problem remains. Is it a bug or temporary restriction? If not, should a note be added to the specs?
Apr 09 2007
prev sibling parent reply JScott <jnl417 gmail.com> writes:
Max Samukha Wrote:

 Why recursive mixins are disallowed?
 
 template Call(A...)
 {
     static if (A.length > 0)
     {
         void call(A[0] fn)
         {
         }
 
         mixin Call!(A[1..$]);
     }
 }
 
 class Caller(A...)
 {
     mixin Call!(A);
 }
 
 void main()
 {
     auto caller = new Caller!(int delegate(), char[] delegate());
 }
 
 hello.d(15): mixin hello.Caller!(int delegate(),char[]
 delegate()).Caller.Call!(int delegate(),char[]
 delegate()).Call!(char[] delegate()).Call!() recursive mixin
 instantiation
 hello.d(26): template instance hello.Caller!(int delegate(),char[]
 delegate()) error instantiating
 
 
I would assume that this is not allowed because of the way mixin templates work. Everytime you instanciate a template as a mixin a new scope is created so it's possible to create a symbol with too long of a name. Now that there are mixins and compile-time execution of functions it's possible to do what you want. template Call(A...) { static if(A.length == 0) const char[] Call = ""; else static if(A.length == 1 ) const char[] Call = "void call("~(typeof(A[0])).stringof~" fn) { \n \n }"; else const char[] Call = "void call("~(typeof(A[0])).stringof~" fn) { \n \n } \n" ~ Call!(A[1..$]); } class Caller(A...) { mixin(Call!(A)); }
Apr 12 2007
parent Max Samukha <samukha voliacable.com> writes:
On Thu, 12 Apr 2007 08:56:16 -0400, JScott <jnl417 gmail.com> wrote:

Max Samukha Wrote:

 Why recursive mixins are disallowed?
 
 template Call(A...)
 {
     static if (A.length > 0)
     {
         void call(A[0] fn)
         {
         }
 
         mixin Call!(A[1..$]);
     }
 }
 
 class Caller(A...)
 {
     mixin Call!(A);
 }
 
 void main()
 {
     auto caller = new Caller!(int delegate(), char[] delegate());
 }
 
 hello.d(15): mixin hello.Caller!(int delegate(),char[]
 delegate()).Caller.Call!(int delegate(),char[]
 delegate()).Call!(char[] delegate()).Call!() recursive mixin
 instantiation
 hello.d(26): template instance hello.Caller!(int delegate(),char[]
 delegate()) error instantiating
 
 
I would assume that this is not allowed because of the way mixin templates work. Everytime you instanciate a template as a mixin a new scope is created so it's possible to create a symbol with too long of a name. Now that there are mixins and compile-time execution of functions it's possible to do what you want. template Call(A...) { static if(A.length == 0) const char[] Call = ""; else static if(A.length == 1 ) const char[] Call = "void call("~(typeof(A[0])).stringof~" fn) { \n \n }"; else const char[] Call = "void call("~(typeof(A[0])).stringof~" fn) { \n \n } \n" ~ Call!(A[1..$]); } class Caller(A...) { mixin(Call!(A)); }
Thanks. I know about the new mixins, but the bodies of functions being mixed in are big in my case and the whole thing quickly turns into an unreadable mess when the new mixins are used.
Apr 16 2007