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();
}