凄いバカなプログラムを作ろう

凄いバカなプログラムを作ろう@きしだのはてなに参加。
初代チャンピオン藤田さんに乗せられ、とりあえず再帰バブルソート書いた。ただ、いろいろ考えたのだけども、単にループを再帰にしただけで全然関数っぽく書けない。しょうがないので「単にYって書きたかっただけじゃないのか」という方向に。

class BakaSort {
    public static void main(String[] args) {
        print(new int[]{14, 13, 71, 2, 24, 19});
        print(new int[]{3, 2});
        print(new int[]{5});
        print(new int[]{});
        print(null);
    }

    //=================================== 準備

    //これが無いと始まらない
    static abstract class λ {
        abstract Object call(Object arg);
    }

    //再帰するのに必要だから
    static λ Y() {
        return new λ() {
                Object call(final Object t) {
                    return new λ() {
                            Object call(final Object s) {
                                return f(t).call(new λ() {
                                        Object call(final Object x) {
                                            return f(f(s).call(s)).call(x);
                                        }});
                            }
                        }.call(new λ() {
                                Object call(final Object s) {
                                    return f(t).call(new λ() {
                                            Object call(final Object x) {
                                                return f(f(s).call(s)).call(x);
                                            }});
                                }});
                }
            };
    }

    //分岐はやっぱり必要かな
    static Object IF(boolean 二度寝しても大丈夫なSICP読書会,λ 入会します,λ 入会しません) {
        for(;二度寝しても大丈夫なSICP読書会;) {
            return 入会します.call(null);
        }
        return 入会しません.call(null);
    }

    //面倒なので
    static λ f(Object f) {return (λ)f;}
    static int[] os(Object o) {return (int[])o;}
    static λ NOP = new λ(){ Object call(Object x) {return null;}};

    //再帰するのに必要だから
    static int[] cdr(final int[] a) {
        return (int[])IF(a == null || a.length == 0,
                         NOP,
                         new λ(){ Object call(Object x) {
                             int[] dest = new int[a.length-1];
                             System.arraycopy(a,1,dest,0,dest.length);
                             return dest;
                         }});
    }

    //=================================== 本体

    //文字列を作って表示
    static void print(final int[] arg) {
        System.out.println
            ( IF(arg == null,
                 new λ() {Object call(Object i) {
                     return "nullです";
                 }},
                 new λ() {Object call(Object i) {
                     return IF(arg.length == 0,
                               new λ() {Object call(Object i) {
                                   return "空です";
                               }},
                               new λ() {Object call(Object i) {
                                   return join(sort(arg));
                               }});
                 }}) );
    }

    //再帰でバブルソート
    static int[] sort(final int[] arg) {
        final λ iter = new λ() {Object call(final Object t) {
            return new λ() {Object call(Object i) {
                final int[] os = os(i);//loop index 0:head, 1:search
                return IF(os[0] == (arg.length-1),
                          new λ(){ Object call(Object a) {
                              return arg;
                          }},
                          new λ(){ Object call(Object a) {
                              return IF(os[1] == arg.length,
                                        new λ(){ Object call(Object a) {
                                            return f(t).call(new int[]{os[0]+1,os[0]+2});
                                        }},
                                        new λ(){ Object call(Object a) {
                                            IF(arg[os[0]] > arg[os[1]],
                                               new λ(){ Object call(Object a) {
                                                   int tmp = arg[os[1]];
                                                   arg[os[1]] = arg[os[0]];
                                                   arg[os[0]] = tmp;
                                                   return null;//これはひどい
                                               }},NOP);
                                            return f(t).call(new int[]{os[0],os[1]+1});
                                        }});
                          }});
            }};
        }};

        //数が少ないときはソートしない
        return (int[])IF(arg.length == 1,
                         new λ(){ Object call(Object a) {
                             return arg;
                         }},
                         new λ(){ Object call(Object a) {
                             return f(Y().call(iter)).call(new int[]{0,1});
                         }});
    }

    //再帰で文字列結合
    static String join(int[] arg) {
        λ pr = new λ() {Object call(final Object t) {
            return new λ() {Object call(Object i) {
                final int[] os = os(i);
                return IF(os == null || os.length == 0,
                          new λ(){ Object call(Object x) {return "";}},
                          new λ(){ Object call(Object a) {
                              return ""+os[0]+" "+f(t).call(cdr(os));
                          }});
            }};
        }};
        return (String)f(Y().call(pr)).call(arg);
    }

}