このファイルコンパイルすると、コンパイルが終わりません!コンパイラが無限ループするっていったいぜんたい。
http://shinh.skr.jp/tmp/functional_endless.d
それはともかく。
http://d.hatena.ne.jp/niha/20061209#1165682303
謎を色々追うにはさんに感動して色々ほげほげしていたところ、 delegate 通りました。「そういえばfuncptrとかあるしdelegateがaliasで渡されたらfunctionに…って出来ないかな」というにはさんの発言をそのまま実装しただけですが。
まぁ皮かぶせてるだけでかっこ悪いので、できればそのまま呼べるようにして下さい。
import std.typetuple;
import std.traits;
import std.stdio;
class Functional_(alias func, int n = 0){
static:
alias ReturnType!(func) Ret;
alias ParameterTypeTuple!(func)[0..n] preArgs;
alias ParameterTypeTuple!(func)[n..$] Args;
ReturnType!(f!(T)) opCall(T...)(T t){
return f!(T)(t);
}
template f(T...){
static assert(ArgsCheck!(Args.length, Args, T), "bad parameter error");
static if (is(T == Args)){
Ret f(Args args){
return func(args_, args);
}
} else {
Functional_!(func, T.length) f(T t){
return new Functional_!(func, T.length)(t);
}
}
}
this(preArgs args){
foreach(i,x; args){
args_[i] = x;
}
}
private:
preArgs args_;
template ArgsCheck(int n, T...){
static if (is(T[0..n] == T[n..$])){
const ArgsCheck = true;
} else static if (n == 0){
const ArgsCheck = false;
} else {
const ArgsCheck = ArgsCheck!(n-1, T[0..n-1], T[n..$]);
}
}
}
template Functional(alias func) {
static if (is (typeof(func) == delegate)) {
alias Functional_!(function ReturnType!(func) (ParameterTypeTuple!(func) a) { return func(a); }) Functional;
}
else {
alias Functional_!(func) Functional;
}
}
int f(int x, int y){ // 普通の関数宣言
return x + y;
}
Functional!(f) func; // 新スタイルの関数宣言!
Functional!((int x, int y){ return x + y; }) funcd;
Functional!(function int (int x, int y){ return x + y; }) funcf;
void main(){
writefln(func(3,4)); // 7
auto x = func(4);
writefln(x(2)); // 6
writefln(func(1)(6)); // 5
writefln(funcd(3, 4));
auto fd = funcd(2);
writefln(fd(1));
writefln(funcf(7, 10));
auto ff = funcf(2);
writefln(ff(7));
}