次は型の調整に挑戦してみるよー.
http://d.hatena.ne.jp/haru-s/20080707/1215425417
ということで,時間ができたのでやりました.
フルスクラッチのD言語用bindがここまで動いたよ!
import std.stdio; import stdex.bind; T[] removeIf(alias cond, T)(T[] arr) { T[] ret; foreach (v; arr) if (!cond(v)) ret ~= v; return ret; } void main() { int[] arr = [1,2,3,4,5,6,7,8,9]; auto less = (int i, int j){return i<j;}; auto lessThan6 = bindAlias!(less)(_0, 6); auto greaterThan5 = bindAlias!(less)(5, _0); writefln(removeIf!(lessThan6)(arr)); writefln(removeIf!(greaterThan5)(arr)); static int sub(int a, int b){return a-b;}; auto a = bindAlias!(sub)(_0, _1); auto b = bindAlias!(sub)(_1, _0); auto c = bindAlias!(sub)(_0, 5); auto d = bindAlias!(sub)(10, _0); auto e = bindAlias!(sub)(10, 5); auto f = bindAlias!(sub)(_0, _0); writefln(a(10,5)); // 5 writefln(b(10,5)); // -5 writefln(c(10)); // 5 writefln(d(5)); // 5 writefln(e()); // 5 writefln(f(10)); // 0 // 型の調整(new!) auto n = (int x, long y){return x*y;}; auto m = (int x, double y){return x*y;}; writefln(bindAlias!(n)(_0,_0)(3));//9; opCall(long)を作って呼ぶ writefln(bindAlias!(m)(_0,_0)(4));//16; opCall(int)を作って呼ぶ //writefln(bindAlias!(m)(_0,_0)(4.0));//opCall(int)にはdoubleを渡せずエラー ////////////////////////////////////////////// // 現在の制限 // /+ // out/ref引数は扱えない auto f = (ref int a){a = 1;}; int x = 2; f(x); writefln(x); // 2 x = 3; auto fx = bindAlias!(f)(&x); fx(); writefln(x); // 3 +/ /+ // 関数合成はできない auto g = (int x, int y){return x*y;}; // g(x, y) = x * y auto h = (int x){return 2*x;}; // h(x) = 2 * x auto gh = bindAlias!(h)( bindAlias!(g)(_0, 3) ); // h(g(x, 3)) = h(x * 3) == 2 * (x * 3) writefln(gh(5)); // 30 +/ }
相変わらず同じようなコードが氾濫してるstdex.bindは続きをどうぞ.
module stdex.bind; import std.traits; import std.typetuple; struct DynArg(int i){static invariant uint id = i;} DynArg!(0) _0; DynArg!(1) _1; DynArg!(2) _2; DynArg!(3) _3; DynArg!(4) _4; DynArg!(5) _5; DynArg!(6) _6; DynArg!(7) _7; DynArg!(8) _8; DynArg!(9) _9; //TLの中にTがいくつあるか template numType(T, TL...) { template loop(int i, TList...) { alias Erase!(T, TList) ErasedTL; static if (is(ErasedTL == TList)) alias i pre; else alias loop!(i+1, ErasedTL).pre pre; } enum numType = loop!(0,TL).pre; } //TLの中のTがあるすべてのインデックス番号を得る template AllIndexesOf(T, TL...) { template loop(int i, IndexList...) { enum index = indexOf!(T, TL[i..$]); static if (index == -1) alias IndexList pre; //もうない else alias loop!(i+index+1, TypeTuple!(IndexList, i+index)).pre pre; //あった } alias loop!(0).pre AllIndexesOf; } template NewParameterTuple(alias func, TL...) { // 生関数の引数 alias ParameterTypeTuple!(func) FuncParams; //pragma(msg, Params[indexDyn0]); //pragma(msg, Params[0]); //pragma(msg, Params[1]); // DynArgが使われているパラメータの共通の型を得る mixin DynArgNType!(0) DynArg0Type; //pragma(msg, DynArg0Type.result); mixin DynArgNType!(1) DynArg1Type; //pragma(msg, DynArg1Type.result); mixin DynArgNType!(2) DynArg2Type; mixin DynArgNType!(3) DynArg3Type; mixin DynArgNType!(4) DynArg4Type; mixin DynArgNType!(5) DynArg5Type; mixin DynArgNType!(6) DynArg6Type; mixin DynArgNType!(7) DynArg7Type; mixin DynArgNType!(8) DynArg8Type; mixin DynArgNType!(9) DynArg9Type; alias ReplaceAll!(DynArg!(0), DynArg0Type.result, TL) T0; alias ReplaceAll!(DynArg!(1), DynArg1Type.result, T0) T1; alias ReplaceAll!(DynArg!(2), DynArg2Type.result, T1) T2; alias ReplaceAll!(DynArg!(3), DynArg3Type.result, T2) T3; alias ReplaceAll!(DynArg!(4), DynArg4Type.result, T3) T4; alias ReplaceAll!(DynArg!(5), DynArg5Type.result, T4) T5; alias ReplaceAll!(DynArg!(6), DynArg6Type.result, T5) T6; alias ReplaceAll!(DynArg!(7), DynArg7Type.result, T6) T7; alias ReplaceAll!(DynArg!(8), DynArg8Type.result, T7) T8; alias ReplaceAll!(DynArg!(9), DynArg9Type.result, T8) T9; alias T9 Params; //pragma(msg, Params); // 引数リストの何番目に(最初の)DynArgがあるか enum indexDyn0 = indexOf!(DynArg!(0),TL); enum indexDyn1 = indexOf!(DynArg!(1),TL); enum indexDyn2 = indexOf!(DynArg!(2),TL); enum indexDyn3 = indexOf!(DynArg!(3),TL); enum indexDyn4 = indexOf!(DynArg!(4),TL); enum indexDyn5 = indexOf!(DynArg!(5),TL); enum indexDyn6 = indexOf!(DynArg!(6),TL); enum indexDyn7 = indexOf!(DynArg!(7),TL); enum indexDyn8 = indexOf!(DynArg!(8),TL); enum indexDyn9 = indexOf!(DynArg!(9),TL); // DynArgを使っている部分に対応するfuncの引数の型だけを得る static if (indexDyn0 == -1) alias void NewParams; else static if (indexDyn1 == -1) alias TypeTuple!(Params[indexDyn0]) NewParams; else static if (indexDyn2 == -1) alias TypeTuple!(Params[indexDyn0], Params[indexDyn1]) NewParams; else static if (indexDyn3 == -1) alias TypeTuple!(Params[indexDyn0], Params[indexDyn1], Params[indexDyn2]) NewParams; else static if (indexDyn4 == -1) alias TypeTuple!(Params[indexDyn0], Params[indexDyn1], Params[indexDyn2], Params[indexDyn3]) NewParams; else static if (indexDyn5 == -1) alias TypeTuple!(Params[indexDyn0], Params[indexDyn1], Params[indexDyn2], Params[indexDyn3], Params[indexDyn4]) NewParams; else static if (indexDyn6 == -1) alias TypeTuple!(Params[indexDyn0], Params[indexDyn1], Params[indexDyn2], Params[indexDyn3], Params[indexDyn4], Params[indexDyn5]) NewParams; else static if (indexDyn7 == -1) alias TypeTuple!(Params[indexDyn0], Params[indexDyn1], Params[indexDyn2], Params[indexDyn3], Params[indexDyn4], Params[indexDyn5], Params[indexDyn6]) NewParams; else static if (indexDyn8 == -1) alias TypeTuple!(Params[indexDyn0], Params[indexDyn1], Params[indexDyn2], Params[indexDyn3], Params[indexDyn4], Params[indexDyn5], Params[indexDyn6], Params[indexDyn7]) NewParams; else static if (indexDyn9 == -1) alias TypeTuple!(Params[indexDyn0], Params[indexDyn1], Params[indexDyn2], Params[indexDyn3], Params[indexDyn4], Params[indexDyn5], Params[indexDyn6], Params[indexDyn7], Params[indexDyn8]) NewParams; else alias TypeTuple!(Params[indexDyn0], Params[indexDyn1], Params[indexDyn2], Params[indexDyn3], Params[indexDyn4], Params[indexDyn5], Params[indexDyn6], Params[indexDyn7], Params[indexDyn8], Params[indexDyn9]) NewParams; // //pragma(msg, NewParams); //pragma(msg,numType!(int, TL).numType); // 2 //pragma(msg,AllIndexesOf!(int, TL).AllIndexesOf); // (1, 3) } template DynArgNType(int N) { alias AllIndexesOf!(DynArg!(N),TL).AllIndexesOf indexesDynN; enum len = indexesDynN.length; alias Sort!(len, indexesDynN, FuncParams).result[0] result; } template Sort(int lenIndexes, TL...) { alias TL[0..lenIndexes] indexes; alias TL[lenIndexes..$] Params; //pragma(msg, indexes); //pragma(msg, indexes.length); //pragma(msg, Params); static if (indexes.length == 0) alias void result; else static if (indexes.length == 1) alias DerivedToFront!(Params[indexes[0]]) result; else static if (indexes.length == 2) alias DerivedToFront!(Params[indexes[0]], Params[indexes[1]]) result; else static if (indexes.length == 3) alias DerivedToFront!(Params[indexes[0]], Params[indexes[1]], Params[indexes[2]]) result; else static if (indexes.length == 4) alias DerivedToFront!(Params[indexes[0]], Params[indexes[1]], Params[indexes[2]], Params[indexes[3]]) result; else static if (indexes.length == 5) alias DerivedToFront!(Params[indexes[0]], Params[indexes[1]], Params[indexes[2]], Params[indexes[3]], Params[indexes[4]]) result; else static if (indexes.length == 6) alias DerivedToFront!(Params[indexes[0]], Params[indexes[1]], Params[indexes[2]], Params[indexes[3]], Params[indexes[4]], Params[indexes[5]]) result; else static if (indexes.length == 7) alias DerivedToFront!(Params[indexes[0]], Params[indexes[1]], Params[indexes[2]], Params[indexes[3]], Params[indexes[4]], Params[indexes[5]], Params[indexes[6]]) result; else static if (indexes.length == 8) alias DerivedToFront!(Params[indexes[0]], Params[indexes[1]], Params[indexes[2]], Params[indexes[3]], Params[indexes[4]], Params[indexes[5]], Params[indexes[6]], Params[indexes[7]]) result; else static if (indexes.length == 9) alias DerivedToFront!(Params[indexes[0]], Params[indexes[1]], Params[indexes[2]], Params[indexes[3]], Params[indexes[4]], Params[indexes[5]], Params[indexes[6]], Params[indexes[7]], Params[indexes[8]]) result; else static if (indexes.length == 10) alias DerivedToFront!(Params[indexes[0]], Params[indexes[1]], Params[indexes[2]], Params[indexes[3]], Params[indexes[4]], Params[indexes[5]], Params[indexes[6]], Params[indexes[7]], Params[indexes[8]], Params[indexes[9]]) result; else static assert(false); } class BoundFunc(alias func, TL...) { alias ReturnType!(func) RetValue; alias NewParameterTuple!(func, TL).NewParams NewParams; //pragma(msg,TL); //pragma(msg,RetValue); //pragma(msg,Params); TL args; this(TL args) { this.args = args; } static if (is(NewParams == void)) { RetValue opCall() { return func(args); } } else { RetValue opCall(NewParams params) { static if (0 < TL.length) { static if (isDynArg!(TL[0])) enum Arg0 = params[TL[0].id]; else enum Arg0 = args[0]; //pragma(msg,typeof(args)[0].id); //pragma(msg,NewParameterTuple!(func, TL).indexDyn0); } static if (1 < TL.length) { static if (isDynArg!(TL[1])) enum Arg1 = params[TL[1].id]; else enum Arg1 = args[1]; //pragma(msg,typeof(args)[0].id); //pragma(msg,typeof(args)[1].id); //pragma(msg,Arg0); //pragma(msg,Arg1); //pragma(msg,NewParameterTuple!(func, TL).indexDyn1); } static if (2 < TL.length) { static if (isDynArg!(TL[2])) enum Arg2 = params[TL[2].id]; else enum Arg2 = args[2]; } static if (3 < TL.length) { static if (isDynArg!(TL[3])) enum Arg3 = params[TL[3].id]; else enum Arg3 = args[3]; } static if (4 < TL.length) { static if (isDynArg!(TL[4])) enum Arg4 = params[TL[4].id]; else enum Arg4 = args[4]; } static if (5 < TL.length) { static if (isDynArg!(TL[5])) enum Arg5 = params[TL[5].id]; else enum Arg5 = args[5]; } static if (6 < TL.length) { static if (isDynArg!(TL[6])) enum Arg6 = params[TL[6].id]; else enum Arg6 = args[6]; } static if (7 < TL.length) { static if (isDynArg!(TL[7])) enum Arg7 = params[TL[7].id]; else enum Arg7 = args[7]; } static if (8 < TL.length) { static if (isDynArg!(TL[8])) enum Arg8 = params[TL[8].id]; else enum Arg8 = args[8]; } static if (9 < TL.length) { static if (isDynArg!(TL[9])) enum Arg9 = params[TL[9].id]; else enum Arg9 = args[9]; } static if (TL.length == 1) return func(Arg0); else static if (TL.length == 2) return func(Arg0, Arg1); else static if (TL.length == 3) return func(Arg0, Arg1, Arg2, Arg3); else static if (TL.length == 4) return func(Arg0, Arg1, Arg2, Arg3, Arg4); else static if (TL.length == 5) return func(Arg0, Arg1, Arg2, Arg3, Arg4, Arg5); else static if (TL.length == 6) return func(Arg0, Arg1, Arg2, Arg3, Arg4, Arg5, Arg6); else static if (TL.length == 7) return func(Arg0, Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7); else static if (TL.length == 8) return func(Arg0, Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8); else static if (TL.length == 9) return func(Arg0, Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8, Arg9); else static assert(false);// 生関数の引数が多すぎます } } } template isDynArg(T) { static if (is(T == DynArg!(0)) || is(T == DynArg!(1)) || is(T == DynArg!(2)) || is(T == DynArg!(3)) || is(T == DynArg!(4)) || is(T == DynArg!(5)) || is(T == DynArg!(6)) || is(T == DynArg!(7)) || is(T == DynArg!(8)) || is(T == DynArg!(9))) { enum isDynArg = true; } else { enum isDynArg = false; } } template bindAlias(alias func) { BoundFunc!(func, TL) bindAlias(TL...)(TL args) { return new BoundFunc!(func, TL)(args); } }