終わらないうたをうたおう

このファイルコンパイルすると、コンパイルが終わりません!コンパイラが無限ループするっていったいぜんたい。

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));
}
なにかあれば下記メールアドレスへ。
shinichiro.hamaji _at_ gmail.com
shinichiro.h