www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - problem with template arguments deduction

reply "Zhenya" <zheny list.ru> writes:
Some time ago I decided to write in D something like boost :: 
bind.But I encountered a problem that the compiler can not deduce 
the template function. Here are a significant part of the code:

template Combination(alias indeces,U...)
{
//	static if(is(typeof(indeces) : uint[]))
//	{
		static if(indeces.length > 1)
			alias TypeTuple!(U[indeces[0]],Combination!(indeces[1..$],U)) 
Combination;
		else static if(indeces.length == 1)
			alias U[indeces[0]] Combination;
//	}
}

template bind(alias indeces)
{
//	static if(is(typeof(indeces) : uint[]))
//	{
		auto bind(R,U...)(R delegate(U) dg,Combination!(indeces,U) 
values)
		{
/*			static if(indeces.length > 1)
				return 
bind!(update!(indeces,indeces[0]))(Curry!(indeces[0])(dg,values[0]),values[1..$]);
			else static if(indeces.length == 1)
				return Curry!(indeces[0])(dg,values[0]);
*/		}
//	}
}

void main()
{
	void xyz(int x,int y,int z)
	{
		writeln("x = ",x," y = ",y," z = ",z);
	}
//	auto g = Curry!1(&xyz,cast(int)(1.1));
//	g(2,3);
	alias Combination!([0,1],int,int,int) Arg;
	Arg a;
	bind!([0,1])(&xyz,a);
	readln();
}

Please, explain to me what is wrong with this code
May 30 2012
next sibling parent reply Philippe Sigaud <philippe.sigaud gmail.com> writes:
I don't see anything wrong per se. It's mainly that the compiler type
extraction/deduction is not powerful enough to extract U in your case.
You can help it a bit by using std.traits.ParameterTypeTuple:

module test;

import std.stdio;
import std.traits;
import std.typetuple;

template Combination(alias indices,U...)
{
    static if(is(typeof(indices) : int[]))
    {
        static if(indices.length > 1)
            alias
TypeTuple!(U[indices[0]],Combination!(indices[1..$],U)) Combination;
        else static if(indices.length == 1)
            alias U[indices[0]] Combination;
    }
}

template bind(alias indices)
{
   static if(is(typeof(indices) : int[]))
   {
        auto bind(D,V...)(D dg, V values) if (is (D d == R
delegate(U), R, U...) && is(V == Combination!(indices,
ParameterTypeTuple!D)))
        {
/*                      static if(indices.length > 1)
                               return
bind!(update!(indices,indices[0]))(Curry!(indices[0])(dg,values[0]),values[1..$]);
                       else static if(indices.length == 1)
                               return Curry!(indices[0])(dg,values[0]);
*/

        }
    }
}

void main()
{
       void xyz(int x,int y,int z)
       {
               writeln("x = ",x," y = ",y," z = ",z);
       }
//      auto g = Curry!1(&xyz,cast(int)(1.1));
//      g(2,3);
       alias Combination!([0,1],int,int,int) Arg;
       Arg a;
       writeln(Arg.stringof);
       bind!([0,1])(&xyz,a);
       //readln();
}
May 30 2012
parent reply Dmitry Olshansky <dmitry.olsh gmail.com> writes:
On 31.05.2012 10:31, Zhenya wrote:
 And, one more thing
 if we have the following code:
 template foo (T)
 {
 auto foo (U) (U arg)
 {
 }
 }
 ...
 foo!(int)('!');
 determine whether the compiler that this specialization is to an
 external template?

If you happen to be Russian, feel free to include Russian as well. I might help translate it ;) As is your question is ... hardly understandable. -- Dmitry Olshansky
May 31 2012
parent reply Dmitry Olshansky <dmitry.olsh gmail.com> writes:
On 01.06.2012 15:16, Zhenya wrote:
 Но тогда почему при замене Bind -> bind
 вот этот код не компилируется?
 module main;

 import std.stdio;
 import std.typecons;
 import std.typetuple;
 import std.traits;

 template Erase(int k,TList...)
 {
 static if(k != 0)
 alias TypeTuple!(TList[0],Erase!(k-1,TList[1..$])) Erase;
 else
 alias TList[1..$] Erase;
 }

 auto Curry(uint i,R,T,U...)(R delegate(U) dg, T arg)
 {
 struct Foo
 {
 typeof(dg) m_dg;
 T m_arg;
 R bar(Erase!(i,U) args)
 {
 U m_args;
 static if(i > 0)
 m_args[0..i] = args[0..i];
 m_args[i] = m_arg;
 static if(i < args.length)
 m_args[i+1..$] = args[i..$];
 return m_dg(m_args);
 }
 }
 Foo* f = new Foo;
 f.m_dg = dg;
 f.m_arg = arg;
 return &f.bar;
 }

 template Combination(alias indeces,U...)
 {
 static if(is(typeof(indeces) : int[]))
 {
 static if(indeces.length > 1)
 alias TypeTuple!(U[indeces[0]],Combination!(indeces[1..$],U)) Combination;
 else static if(indeces.length == 1)
 alias TypeTuple!(U[indeces[0]]) Combination;
 }
 }

 template update(alias indeces,int current)
 {
 static if(is(typeof(indeces) : int[]))
 {
 static if(indeces.length > 1)
 {
 static if(indeces[0] > current)
 enum int[] update = (indeces[0]-1)~update!(indeces[1..$],current);
 else
 enum int[] update = indeces[0]~update!(indeces[1..$],current);
 }
 else static if(indeces.length == 1)
 {
 static if(indeces[0] > current)
 enum int[] update = [indeces[0]-1];
 else
 alias indeces update;
 }
 }
 }

 template Bind(alias indeces)
 {
 static if(is(typeof(indeces) : int[]))
 {
 auto bind(D,V...)(D dg,V values)
 {
 static if(is(D d : R delegate(U), R, U...) &&
 is(V == Combination!(indeces,ParameterTypeTuple!D)))
 {
 static if(indeces.length > 1)
 return
 Bind!(update!(indeces,indeces[0])[1..$]).bind(Curry!(indeces[0])(dg,values[0]),values[1..$]);

 else static if(indeces.length == 1)
 return Curry!(indeces[0])(dg,values[0]);
 }
 }
 }
 }

 void main()
 {
 void checker(T...)(T args)
 {
 foreach(i,current;args)
 {
 writeln("x",i," = ",current);
 }
 }
 Bind!([1,0,3]).bind(&checker!(int,int,int,int),2,1,4)(3);

Может все-таки Bind!([1,0,3], &checker!(int, int, int, int), 2, 1, 4)(3) т.е. изначально имелось в виду Bind!([1,0,3]).bind!(&checker!(int,int,int,int),2,1,4)(3) ? тогда должно работать. Иными словами не более одного списка !(...). Компилятор не ошибется выбирая из него аргументы слева направо по мере необходимости.
 readln();
 }

-- Dmitry Olshansky
Jun 01 2012
parent reply Dmitry Olshansky <dmitry.olsh gmail.com> writes:
On 01.06.2012 15:40, Zhenya wrote:
 On Friday, 1 June 2012 at 11:23:48 UTC, Dmitry Olshansky wrote:
 On 01.06.2012 15:16, Zhenya wrote:
 Но тогда почему при замене Bind -> bind
 вот этот код не компилируется?
 module main;

 import std.stdio;
 import std.typecons;
 import std.typetuple;
 import std.traits;

 template Erase(int k,TList...)
 {
 static if(k != 0)
 alias TypeTuple!(TList[0],Erase!(k-1,TList[1..$])) Erase;
 else
 alias TList[1..$] Erase;
 }

 auto Curry(uint i,R,T,U...)(R delegate(U) dg, T arg)
 {
 struct Foo
 {
 typeof(dg) m_dg;
 T m_arg;
 R bar(Erase!(i,U) args)
 {
 U m_args;
 static if(i > 0)
 m_args[0..i] = args[0..i];
 m_args[i] = m_arg;
 static if(i < args.length)
 m_args[i+1..$] = args[i..$];
 return m_dg(m_args);
 }
 }
 Foo* f = new Foo;
 f.m_dg = dg;
 f.m_arg = arg;
 return &f.bar;
 }

 template Combination(alias indeces,U...)
 {
 static if(is(typeof(indeces) : int[]))
 {
 static if(indeces.length > 1)
 alias TypeTuple!(U[indeces[0]],Combination!(indeces[1..$],U))
 Combination;
 else static if(indeces.length == 1)
 alias TypeTuple!(U[indeces[0]]) Combination;
 }
 }

 template update(alias indeces,int current)
 {
 static if(is(typeof(indeces) : int[]))
 {
 static if(indeces.length > 1)
 {
 static if(indeces[0] > current)
 enum int[] update = (indeces[0]-1)~update!(indeces[1..$],current);
 else
 enum int[] update = indeces[0]~update!(indeces[1..$],current);
 }
 else static if(indeces.length == 1)
 {
 static if(indeces[0] > current)
 enum int[] update = [indeces[0]-1];
 else
 alias indeces update;
 }
 }
 }

 template Bind(alias indeces)
 {
 static if(is(typeof(indeces) : int[]))
 {
 auto bind(D,V...)(D dg,V values)
 {
 static if(is(D d : R delegate(U), R, U...) &&
 is(V == Combination!(indeces,ParameterTypeTuple!D)))
 {
 static if(indeces.length > 1)
 return
 Bind!(update!(indeces,indeces[0])[1..$]).bind(Curry!(indeces[0])(dg,values[0]),values[1..$]);


 else static if(indeces.length == 1)
 return Curry!(indeces[0])(dg,values[0]);
 }
 }
 }
 }

 void main()
 {
 void checker(T...)(T args)
 {
 foreach(i,current;args)
 {
 writeln("x",i," = ",current);
 }
 }
 Bind!([1,0,3]).bind(&checker!(int,int,int,int),2,1,4)(3);

Может все-таки Bind!([1,0,3], &checker!(int, int, int, int), 2, 1, 4)(3) т.е. изначально имелось в виду Bind!([1,0,3]).bind!(&checker!(int,int,int,int),2,1,4)(3) ? тогда должно работать. Иными словами не более одного списка !(...). Компилятор не ошибется выбирая из него аргументы слева направо по мере необходимости.
 readln();
 }


времени выполнения.Значит: bind!([1,0,3])(&checker!(int,int,int,int),2,1,4)(3) но не хочет компилится(

Лог ошибок в студию. -- Dmitry Olshansky
Jun 01 2012
parent reply Dmitry Olshansky <dmitry.olsh gmail.com> writes:
On 01.06.2012 15:47, Zhenya wrote:
 Error 3 Error: function expected before (), not bind(&checker,2,1,4) of
 type _error_ c:\users\zhenya\documents\visual studio
 2010\Projects\D\ConsoleApp1\ConsoleApp1\main.d 98

 Error 1 Error: template instance bind!([0,2]) bind!([0,2]) does not
 match template declaration bind(D,V...) c:\users\zhenya\documents\visual
 studio 2010\Projects\D\ConsoleApp1\ConsoleApp1\main.d 81

 Error 2 Error: template instance main.bind!([1,0,3]).bind!(void
 delegate(int _param_0, int _param_1, int _param_2, int _param_3)
  system,int,int,int) error instantiating
 c:\users\zhenya\documents\visual studio
 2010\Projects\D\ConsoleApp1\ConsoleApp1\main.d 98

It may have some problem with matching this delegate hmmm. What if you try this: template Bind(alias indeces) if(is(typeof(indeces) : int[])) { auto bind(V...)(alias dg,V values) if(is(V == Combination!(indeces,ParameterTypeTuple!D))) { static if(indeces.length > 1) return Bind!(update!(indeces,indeces[0])[1..$]).bind(Curry! (indeces[0]) (dg,values[0]),values[1..$]); else assert(0); } } alias instead of delegate - it's just more powerful I relaxed constraints and static ifs ---> proper template constraints. -- Dmitry Olshansky
Jun 01 2012
parent reply Dmitry Olshansky <dmitry.olsh gmail.com> writes:
On 01.06.2012 16:47, Zhenya wrote:
 On Friday, 1 June 2012 at 12:38:11 UTC, Dmitry Olshansky wrote:
 On 01.06.2012 15:47, Zhenya wrote:
 Error 3 Error: function expected before (), not bind(&checker,2,1,4) of
 type _error_ c:\users\zhenya\documents\visual studio
 2010\Projects\D\ConsoleApp1\ConsoleApp1\main.d 98

 Error 1 Error: template instance bind!([0,2]) bind!([0,2]) does not
 match template declaration bind(D,V...) c:\users\zhenya\documents\visual
 studio 2010\Projects\D\ConsoleApp1\ConsoleApp1\main.d 81

 Error 2 Error: template instance main.bind!([1,0,3]).bind!(void
 delegate(int _param_0, int _param_1, int _param_2, int _param_3)
  system,int,int,int) error instantiating
 c:\users\zhenya\documents\visual studio
 2010\Projects\D\ConsoleApp1\ConsoleApp1\main.d 98

It may have some problem with matching this delegate hmmm. What if you try this: template Bind(alias indeces) if(is(typeof(indeces) : int[])) { auto bind(alias dg, V...)(V values) if(is(V == Combination!(indeces,ParameterTypeTuple!D))) { static if(indeces.length > 1) return Bind!(update!(indeces,indeces[0])[1..$]).bind(Curry! (indeces[0]) (dg,values[0]),values[1..$]); else assert(0); } } alias instead of delegate - it's just more powerful I relaxed constraints and static ifs ---> proper template constraints.

studio 2010\Projects\D\ConsoleApp1\ConsoleApp1\main.d 75 Похоже что alias не может быть аргументом времени выполнения

ну как же map, filter и тд работают ) ну передавай свой delegate как параметр времени компиляции через !(...) все будет ок ... auto bind(alias dg, V...)(V values)
 if(is(V == Combination!(indeces,ParameterTypeTuple!D)))
 {
 static if(indeces.length > 1)
 return


Bind!(update!(indeces,indeces[0])[1..$]).bind!(Curry! (indeces[0]) (values[0]),values[1..$]);
 else
 assert(0);
 }
 }


-- Dmitry Olshansky
Jun 01 2012
next sibling parent Dmitry Olshansky <dmitry.olsh gmail.com> writes:
On 01.06.2012 16:53, Zhenya wrote:
 ну как же map, filter и тд работают )
 ну передавай свой delegate как параметр
времени компиляции через !(...)
 все будет ок ...


beats me.
 А это часом не бага у DMD?

Ну их много, заполни репорт в http://d.puremagic.com/issues/ через пару дней Кенжи Хара пофиксит если это баг ) -- Dmitry Olshansky
Jun 01 2012
prev sibling parent reply Dmitry Olshansky <dmitry.olsh gmail.com> writes:
On 02.06.2012 11:23, Zhenya wrote:
 Дмитрий,не подскажите как я бы мог
проверить не баг ли это?

Как я и говорил отписать что это баг. Дальше это дело экспертов по компилятору ) Вот например последние что ты отипсывал, вполне катит для bug-репорта: (только сократи лишний "внешний" код) this doesn't work: template bind(alias indeces) { static if(is(typeof(indeces) : int[])) { auto bind(D,V...)(D dg,V values) { static if(is(D d : R delegate(U), R, U...) && is(V == Combination!(indeces,ParameterTypeTuple!D))) { static if(indeces.length > 1) return bind!(update!(indeces,indeces[0])[1..$]).bind(Curry!(indeces[0])(dg,values[0]),values[1..$]); else static if(indeces.length == 1) return Curry!(indeces[0])(dg,values[0]); } } } } while this works : class Bind(alias indeces) { static auto opCall(D,V...)(D dg,V values) { static if(is(D d : R delegate(U), R, U...) && is(V == Combination!(indeces,ParameterTypeTuple!D))) { static if(indeces.length > 1) return Bind!(update!(indeces,indeces[0])[1..$])(Curry!(indeces[0])(dg,values[0]),values[1..$]); else return Curry!(indeces[0])(dg,values[0]); } } } -- Dmitry Olshansky
Jun 02 2012
parent Dmitry Olshansky <dmitry.olsh gmail.com> writes:
On 02.06.2012 11:30, Zhenya wrote:
 Куда отписать-то?)

-- Dmitry Olshansky
Jun 02 2012
prev sibling next sibling parent "Zhenya" <zheny list.ru> writes:
On Wednesday, 30 May 2012 at 22:19:53 UTC, Philippe Sigaud wrote:
 I don't see anything wrong per se. It's mainly that the 
 compiler type
 extraction/deduction is not powerful enough to extract U in 
 your case.
 You can help it a bit by using std.traits.ParameterTypeTuple:

 module test;

 import std.stdio;
 import std.traits;
 import std.typetuple;

 template Combination(alias indices,U...)
 {
     static if(is(typeof(indices) : int[]))
     {
         static if(indices.length > 1)
             alias
 TypeTuple!(U[indices[0]],Combination!(indices[1..$],U)) 
 Combination;
         else static if(indices.length == 1)
             alias U[indices[0]] Combination;
     }
 }

 template bind(alias indices)
 {
    static if(is(typeof(indices) : int[]))
    {
         auto bind(D,V...)(D dg, V values) if (is (D d == R
 delegate(U), R, U...) && is(V == Combination!(indices,
 ParameterTypeTuple!D)))
         {
 /*                      static if(indices.length > 1)
                                return
 bind!(update!(indices,indices[0]))(Curry!(indices[0])(dg,values[0]),values[1..$]);
                        else static if(indices.length == 1)
                                return 
 Curry!(indices[0])(dg,values[0]);
 */

         }
     }
 }

 void main()
 {
        void xyz(int x,int y,int z)
        {
                writeln("x = ",x," y = ",y," z = ",z);
        }
 //      auto g = Curry!1(&xyz,cast(int)(1.1));
 //      g(2,3);
        alias Combination!([0,1],int,int,int) Arg;
        Arg a;
        writeln(Arg.stringof);
        bind!([0,1])(&xyz,a);
        //readln();
 }

May 30 2012
prev sibling next sibling parent "Zhenya" <zheny list.ru> writes:
And, one more thing
if we have the following code:
template foo (T)
{
         auto foo (U) (U arg)
         {
         }
}
...
foo!(int)('!');
determine whether the compiler that this specialization is to an 
external template?
May 30 2012
prev sibling next sibling parent Philippe Sigaud <philippe.sigaud gmail.com> writes:
On Thu, May 31, 2012 at 8:31 AM, Zhenya <zheny list.ru> wrote:
 And, one more thing
 if we have the following code:
 template foo (T)
 {
 =C2=A0 =C2=A0 =C2=A0 =C2=A0auto foo (U) (U arg)
 =C2=A0 =C2=A0 =C2=A0 =C2=A0{
 =C2=A0 =C2=A0 =C2=A0 =C2=A0}
 }
 ...
 foo!(int)('!');
 determine whether the compiler that this specialization is to an external
 template?

I'm not sure I understand the question?
May 31 2012
prev sibling next sibling parent "Zhenya" <zheny list.ru> writes:
Вот у нас есть такая конструкция
template foo(T)
{
          foo(U)()
          {
          }
}
Могут ли у компилятора при
инстанциировании возникнуть
трудности с пониманием
какие аргументы к какому шаблону
относятся?
Вопрос у меня возник из-за того,что
когда я применил совет Philippe Sigaud
к своему полному коду компилятор не
захотел его компилировать.Но когда
я поменял имя внутреннего шаблона
все стало хорошо.Это ведь
неправильно?
Jun 01 2012
prev sibling next sibling parent "Zhenya" <zheny list.ru> writes:
Вот у нас есть такая конструкция
template foo(T)
{
         foo(U)()
         {
         }
}
Могут ли у компилятора при
инстанциировании возникнуть
трудности с пониманием
какие аргументы к какому шаблону
относятся?
Вопрос у меня возник из-за того,что
когда я применил совет Philippe Sigaud
к своему полному коду компилятор не
захотел его компилировать.Но когда
я поменял имя внутреннего шаблона
все стало хорошо.Это ведь
неправильно?
Jun 01 2012
prev sibling next sibling parent "Zhenya" <zheny list.ru> writes:
Простите меня за мой английский)
Jun 01 2012
prev sibling next sibling parent "Dmitry Olshansky" <dmitry.olsh gmail.com> writes:
On Friday, 1 June 2012 at 08:08:19 UTC, Zhenya wrote:
 Вот у нас есть такая конструкция
 template foo(T)
 {
         foo(U)()
         {
         }
 }
 Могут ли у компилятора при
 инстанциировании возникнуть
 трудности с пониманием
 какие аргументы к какому шаблону
 относятся?
 Вопрос у меня возник из-за того,что
 когда я применил совет Philippe Sigaud
 к своему полному коду компилятор 
 не
 захотел его компилировать.Но когда
 я поменял имя внутреннего шаблона
 все стало хорошо.Это ведь
 неправильно?

In other words: Given this construct:
 template foo(T)
 {
         foo(U)()
         {
         }
 }

which template argument goes to which template here? The question was born when I started applying Philippe Siguad's advice to my full source code compiler rejected it. But when I change inner tmeplate name it worked - it's no good, is it? Вопрос довольно сложный. Краткий ответ - нет, все идет слева направо, сверху вниз. Есть впрочем одно но - компилятор начинает выводить типы из аргументов только для последнего foo (т.е. U). То есть T в это случае дается сверху (тобой через foo!T(...) ). Впрочем в твоем примере foo не моежт вывести U из аргументов (их нет). Difficult Q. In short - no, it's all left-to-right up-to-bottom. However compiler may deduce types only for lowest foo (i.e. U). T in this case have to provided from above (by you as in foo!T(...)). --- It's me, just trying out web interface.
Jun 01 2012
prev sibling next sibling parent "Zhenya" <zheny list.ru> writes:
Но тогда почему при замене Bind -> bind
вот этот код не компилируется?
module main;

import std.stdio;
import std.typecons;
import std.typetuple;
import std.traits;

template Erase(int k,TList...)
{
	static if(k != 0)
		alias TypeTuple!(TList[0],Erase!(k-1,TList[1..$])) Erase;
	else
		alias TList[1..$] Erase;
}

auto Curry(uint i,R,T,U...)(R delegate(U) dg, T arg)
{
	struct Foo
	{
		typeof(dg) m_dg;
		T m_arg;
		R bar(Erase!(i,U) args)
		{
			U m_args;
			static if(i > 0)
				m_args[0..i] = args[0..i];
			m_args[i] = m_arg;
			static if(i < args.length)
				m_args[i+1..$] = args[i..$];
			return m_dg(m_args);
		}
	}
	Foo* f = new Foo;
	f.m_dg = dg;
	f.m_arg  = arg;
	return &f.bar;
}

template Combination(alias indeces,U...)
{
	static if(is(typeof(indeces) : int[]))
	{
		static if(indeces.length > 1)
			alias TypeTuple!(U[indeces[0]],Combination!(indeces[1..$],U)) 
Combination;
		else static if(indeces.length == 1)
			alias TypeTuple!(U[indeces[0]]) Combination;
	}
}

template update(alias indeces,int current)
{
	static if(is(typeof(indeces) : int[]))
	{
		static if(indeces.length > 1)
		{
			static if(indeces[0] > current)
				enum int[] update = 
(indeces[0]-1)~update!(indeces[1..$],current);
			else
				enum int[] update = indeces[0]~update!(indeces[1..$],current);
		}
		else static if(indeces.length == 1)
		{
			static if(indeces[0] > current)
				enum int[] update = [indeces[0]-1];
			else
				alias indeces update;
		}
	}
}

template Bind(alias indeces)
{
	static if(is(typeof(indeces) : int[]))
	{
		auto bind(D,V...)(D dg,V values)
		{
			static if(is(D d : R delegate(U), R, U...) &&
					  is(V == Combination!(indeces,ParameterTypeTuple!D)))
			{
				static if(indeces.length > 1)
					return 
Bind!(update!(indeces,indeces[0])[1..$]).bind(Curry!(indeces[0])(dg,values[0]),values[1..$]);
				else static if(indeces.length == 1)
					return Curry!(indeces[0])(dg,values[0]);
			}
		}
	}
}

void main()
{
	void checker(T...)(T args)
	{
		foreach(i,current;args)
		{
			writeln("x",i," = ",current);
		}
	}
	Bind!([1,0,3]).bind(&checker!(int,int,int,int),2,1,4)(3);
	readln();
}
Jun 01 2012
prev sibling next sibling parent "Zhenya" <zheny list.ru> writes:
On Friday, 1 June 2012 at 11:23:48 UTC, Dmitry Olshansky wrote:
 On 01.06.2012 15:16, Zhenya wrote:
 Но тогда почему при замене Bind -> bind
 вот этот код не компилируется?
 module main;

 import std.stdio;
 import std.typecons;
 import std.typetuple;
 import std.traits;

 template Erase(int k,TList...)
 {
 static if(k != 0)
 alias TypeTuple!(TList[0],Erase!(k-1,TList[1..$])) Erase;
 else
 alias TList[1..$] Erase;
 }

 auto Curry(uint i,R,T,U...)(R delegate(U) dg, T arg)
 {
 struct Foo
 {
 typeof(dg) m_dg;
 T m_arg;
 R bar(Erase!(i,U) args)
 {
 U m_args;
 static if(i > 0)
 m_args[0..i] = args[0..i];
 m_args[i] = m_arg;
 static if(i < args.length)
 m_args[i+1..$] = args[i..$];
 return m_dg(m_args);
 }
 }
 Foo* f = new Foo;
 f.m_dg = dg;
 f.m_arg = arg;
 return &f.bar;
 }

 template Combination(alias indeces,U...)
 {
 static if(is(typeof(indeces) : int[]))
 {
 static if(indeces.length > 1)
 alias TypeTuple!(U[indeces[0]],Combination!(indeces[1..$],U)) 
 Combination;
 else static if(indeces.length == 1)
 alias TypeTuple!(U[indeces[0]]) Combination;
 }
 }

 template update(alias indeces,int current)
 {
 static if(is(typeof(indeces) : int[]))
 {
 static if(indeces.length > 1)
 {
 static if(indeces[0] > current)
 enum int[] update = 
 (indeces[0]-1)~update!(indeces[1..$],current);
 else
 enum int[] update = indeces[0]~update!(indeces[1..$],current);
 }
 else static if(indeces.length == 1)
 {
 static if(indeces[0] > current)
 enum int[] update = [indeces[0]-1];
 else
 alias indeces update;
 }
 }
 }

 template Bind(alias indeces)
 {
 static if(is(typeof(indeces) : int[]))
 {
 auto bind(D,V...)(D dg,V values)
 {
 static if(is(D d : R delegate(U), R, U...) &&
 is(V == Combination!(indeces,ParameterTypeTuple!D)))
 {
 static if(indeces.length > 1)
 return
 Bind!(update!(indeces,indeces[0])[1..$]).bind(Curry!(indeces[0])(dg,values[0]),values[1..$]);

 else static if(indeces.length == 1)
 return Curry!(indeces[0])(dg,values[0]);
 }
 }
 }
 }

 void main()
 {
 void checker(T...)(T args)
 {
 foreach(i,current;args)
 {
 writeln("x",i," = ",current);
 }
 }
 Bind!([1,0,3]).bind(&checker!(int,int,int,int),2,1,4)(3);

Может все-таки Bind!([1,0,3], &checker!(int, int, int, int), 2, 1, 4)(3) т.е. изначально имелось в виду Bind!([1,0,3]).bind!(&checker!(int,int,int,int),2,1,4)(3) ? тогда должно работать. Иными словами не более одного списка !(...). Компилятор не ошибется выбирая из него аргументы слева направо по мере необходимости.
 readln();
 }


(&checker!(int,int,int,int),2,1,4) - аргументы времени выполнения.Значит: bind!([1,0,3])(&checker!(int,int,int,int),2,1,4)(3) но не хочет компилится(
Jun 01 2012
prev sibling next sibling parent "Zhenya" <zheny list.ru> writes:
Error	3	Error: function expected before (), not 
bind(&checker,2,1,4) of type 
_error_	c:\users\zhenya\documents\visual studio 
2010\Projects\D\ConsoleApp1\ConsoleApp1\main.d	98	

Error	1	Error: template instance bind!([0,2]) bind!([0,2]) does 
not match template declaration 
bind(D,V...)	c:\users\zhenya\documents\visual studio 
2010\Projects\D\ConsoleApp1\ConsoleApp1\main.d	81	

Error	2	Error: template instance main.bind!([1,0,3]).bind!(void 
delegate(int _param_0, int _param_1, int _param_2, int _param_3) 
 system,int,int,int) error 
instantiating	c:\users\zhenya\documents\visual studio 
2010\Projects\D\ConsoleApp1\ConsoleApp1\main.d	98	
Jun 01 2012
prev sibling next sibling parent "Zhenya" <zheny list.ru> writes:
On Friday, 1 June 2012 at 12:38:11 UTC, Dmitry Olshansky wrote:
 On 01.06.2012 15:47, Zhenya wrote:
 Error 3 Error: function expected before (), not 
 bind(&checker,2,1,4) of
 type _error_ c:\users\zhenya\documents\visual studio
 2010\Projects\D\ConsoleApp1\ConsoleApp1\main.d 98

 Error 1 Error: template instance bind!([0,2]) bind!([0,2]) 
 does not
 match template declaration bind(D,V...) 
 c:\users\zhenya\documents\visual
 studio 2010\Projects\D\ConsoleApp1\ConsoleApp1\main.d 81

 Error 2 Error: template instance main.bind!([1,0,3]).bind!(void
 delegate(int _param_0, int _param_1, int _param_2, int 
 _param_3)
  system,int,int,int) error instantiating
 c:\users\zhenya\documents\visual studio
 2010\Projects\D\ConsoleApp1\ConsoleApp1\main.d 98

It may have some problem with matching this delegate hmmm. What if you try this: template Bind(alias indeces) if(is(typeof(indeces) : int[])) { auto bind(V...)(alias dg,V values) if(is(V == Combination!(indeces,ParameterTypeTuple!D))) { static if(indeces.length > 1) return Bind!(update!(indeces,indeces[0])[1..$]).bind(Curry! (indeces[0]) (dg,values[0]),values[1..$]); else assert(0); } } alias instead of delegate - it's just more powerful I relaxed constraints and static ifs ---> proper template constraints.

alias c:\users\zhenya\documents\visual studio 2010\Projects\D\ConsoleApp1\ConsoleApp1\main.d 75 Похоже что alias не может быть аргументом времени выполнения
Jun 01 2012
prev sibling next sibling parent "Zhenya" <zheny list.ru> writes:
Да,на всякий случай,текущий 
исходник,который не компилится

module main;

import std.stdio;
import std.typecons;
import std.typetuple;
import std.traits;

template Erase(int k,TList...)
{
	static if(k != 0)
		alias TypeTuple!(TList[0],Erase!(k-1,TList[1..$])) Erase;
	else
		alias TList[1..$] Erase;
}

auto Curry(uint i,R,T,U...)(R delegate(U) dg, T arg)
{
	struct Foo
	{
		typeof(dg) m_dg;
		T m_arg;
		R bar(Erase!(i,U) args)
		{
			U m_args;
			static if(i > 0)
				m_args[0..i] = args[0..i];
			m_args[i] = m_arg;
			static if(i < args.length)
				m_args[i+1..$] = args[i..$];
			return m_dg(m_args);
		}
	}
	Foo* f = new Foo;
	f.m_dg = dg;
	f.m_arg  = arg;
	return &f.bar;
}

template Combination(alias indeces,U...)
{
	static if(is(typeof(indeces) : int[]))
	{
		static if(indeces.length > 1)
			alias TypeTuple!(U[indeces[0]],Combination!(indeces[1..$],U)) 
Combination;
		else static if(indeces.length == 1)
			alias TypeTuple!(U[indeces[0]]) Combination;
	}
}

template update(alias indeces,int current)
{
	static if(is(typeof(indeces) : int[]))
	{
		static if(indeces.length > 1)
		{
			static if(indeces[0] > current)
				enum int[] update = 
(indeces[0]-1)~update!(indeces[1..$],current);
			else
				enum int[] update = indeces[0]~update!(indeces[1..$],current);
		}
		else static if(indeces.length == 1)
		{
			static if(indeces[0] > current)
				enum int[] update = [indeces[0]-1];
			else
				alias indeces update;
		}
	}
}

template bind(alias indeces)
{
	static if(is(typeof(indeces) : int[]))
	{
		auto bind(D,V...)(D dg,V values)
		{
			static if(is(D d : R delegate(U), R, U...) &&
					  is(V == Combination!(indeces,ParameterTypeTuple!D)))
			{
				static if(indeces.length > 1)
					return 
bind!(update!(indeces,indeces[0])[1..$]).bind(Curry!(indeces[0])(dg,values[0]),values[1..$]);
				else static if(indeces.length == 1)
					return Curry!(indeces[0])(dg,values[0]);
			}
		}
	}
}

void main()
{
	void checker(T...)(T args)
	{
		foreach(i,current;args)
		{
			writeln("x",i," = ",current);
		}
	}
	bind!([1,0,3])(&checker!(int,int,int,int),2,1,4)(3);
	readln();
}
Jun 01 2012
prev sibling next sibling parent "Zhenya" <zheny list.ru> writes:
 ну как же map, filter и тд работают )
 ну передавай свой delegate как 
 параметр времени компиляции через 
 !(...)
 все будет ок ...

А это часом не бага у DMD?
Jun 01 2012
prev sibling next sibling parent "Zhenya" <zheny list.ru> writes:
On Friday, 1 June 2012 at 12:53:16 UTC, Zhenya wrote:
 ну как же map, filter и тд работают )
 ну передавай свой delegate как 
 параметр времени компиляции 
 через !(...)
 все будет ок ...

А это часом не бага у DMD?

кстати если я заменяю template bind(alias indeces) { static if(is(typeof(indeces) : int[])) { auto bind(D,V...)(D dg,V values) { static if(is(D d : R delegate(U), R, U...) && is(V == Combination!(indeces,ParameterTypeTuple!D))) { static if(indeces.length > 1) return bind!(update!(indeces,indeces[0])[1..$]).bind(Curry!(indeces[0])(dg,values[0]),values[1..$]); else static if(indeces.length == 1) return Curry!(indeces[0])(dg,values[0]); } } } } на class Bind(alias indeces) { static auto opCall(D,V...)(D dg,V values) { static if(is(D d : R delegate(U), R, U...) && is(V == Combination!(indeces,ParameterTypeTuple!D))) { static if(indeces.length > 1) return Bind!(update!(indeces,indeces[0])[1..$])(Curry!(indeces[0])(dg,values[0]),values[1..$]); else return Curry!(indeces[0])(dg,values[0]); } } } то вот так Bind!([1,0,3])(&checker!(int,int,int,int),2,1,4)(3); вполне спокойно работает в чем же разница?
Jun 01 2012
prev sibling next sibling parent "Zhenya" <zheny list.ru> writes:
Дмитрий,не подскажите как я бы мог 
проверить не баг ли это?
Jun 02 2012
prev sibling parent "Zhenya" <zheny list.ru> writes:
Куда отписать-то?)
Jun 02 2012