[haXe] haXe、変態的過ぎるの巻

なんじゃあこのswitchはぁぁぁぁぁ!!!!!!! OCamlか!!!!!!
って haXe 自体が OCaml で書かれているし。

w.l.o.g.のこのエントリで紹介されていた論文「Derivation of deterministic inverse programs based on LR parsing」に出ているランレングスのサンプルコードをhaXeで書いてみた。

enum ZeroOrMore {
    _;
    cons(f: String, s: ZeroOrMore);
}

enum Pair {
    one(f: String);
    pair(f: String, s: String);
}

class RunLength {
    public function new() {}

    public function deq(param: ZeroOrMore): Pair {
        return switch (param) {
            case cons(f, s):
                switch (s) {
                    case _:
                        pair(f, f);
                    case cons(_f, _s):
                        _s == _ ? (f == _f ? one(f): pair(f, _f)): one(f);
                };
            case _:
                throw "WTF?";
        };
    }

    public function pack(s: ZeroOrMore): ZeroOrMore {
        return switch (s) {
            case _: _;
            case cons(c, r):
                switch (len(c, 1, r)) {
                    case _: _;
                    case cons(p, l): cons(p, pack(l));
                }
        };
    }

    public function len(c: String, n: Int, s: ZeroOrMore): ZeroOrMore {
        return switch (s) {
            case _: cons("<" + c + "," + n + ">", _);
            case cons(d, r):
                switch (deq(cons(c, cons(d, _)))) {
                    case one(e):
                        len(e, n + 1, r);
                    case pair(e, f):
                        cons("<" + e + "," + n + ">", cons(f, r));
                }
        }
    }

    public function toCons(str: Array<String>): ZeroOrMore {
        return str.length == 1 ? cons(str[0], _):
            cons(str.shift(), toCons(str));
    }

    public function fromCons(c: ZeroOrMore): Array<String> {
        return switch (c) {
            case _:
                [];
            case cons(f, s):
                [f].concat(fromCons(s));
        }
    }
}

class Test {
    public static function main(): Void {
        var scope = new RunLength();
        trace(scope.fromCons(scope.pack(scope.toCons([ "A", "A", "B", "C", "C", "C", "D" ]))));
    }
}

コンパイルと実行:

haxe -main Test -n Test.n Test.hx
neko Test.n

出力結果:

Test.hx:70: [<A,2>, <B,1>, <C,3>, <D,1>]

うーん、もうしばらくhaXeにどっぷり浸かろう。
これはいい言語かも。