もっとちゃんとした curry

() で括られた list を splice するのが困難と思い込んでたので随分遠回りしてしまった。C macro は turing machine よりずっと弱いので、引数が制限されるのは不可避。それを除けば結構関数っぽく使える。

あー面白かった(マテ

#define INFLATE_()
#define INFLATE__(a0) a0,
#define INFLATE___(a0, a1) a0, a1,
#define INFLATE____(a0, a1, a2) a0, a1, a2,
#define INFLATE_____(a0, a1, a2, a3) a0, a1, a2, a3,
#define INFLATE______(a0, a1, a2, a3, a4) a0, a1, a2, a3, a4,
#define INFLATE_______(a0, a1, a2, a3, a4, a5) a0, a1, a2, a3, a4, a5,
#define INFLATE________  __you_are_feeding_me_too_much_curry__

#define CAT(a, b)      a##b
#define LPAREN         (
#define RPAREN         )
#define EVAL_CAT(a, b) CAT(a, b)
#define EMPTY()
#define OP_P           ((), _,
#if 0
                        ));     /* Appease the indenter. */
#endif
#define OP_I(a, l, f)  (a, l, f)
#define CANCEL_PAREN   EMPTY LPAREN
#define P(a, l, f)     I(a, l, f) CANCEL_PAREN
#define WRAP(f)        P f RPAREN
#define FIXUP(f)       EVAL_CAT(OP_, WRAP(f))

#define EVAL(e)          EVAL_INTERNAL(e)
#define EVAL_INTERNAL(e) e
#define COMMA ,

#define ARGS(x, y, z) x
#define PFIX(x, y, z) y
#define PROC(x, y, z) z
#define APPEND(s, x) ((EVAL_CAT(INFLATE, PFIX s) ARGS s x), EVAL_CAT(_, PFIX s), PROC s)

#define CURRY(f, x) EVAL( APPEND LPAREN FIXUP(f) COMMA x RPAREN )
#define CURRY2(f, a1, a2) CURRY(CURRY(f, a1), a2)
#define CURRY3(f, a1, a2, a3) CURRY(CURRY(CURRY(f, a1), a2), a3)
#define CURRY4(f, a1, a2, a3, a4) CURRY(CURRY(CURRY(CURRY(f, a1), a2), a3), a4)
#define INVOKE(x, y, z) z x
#define APPLY_AUX(f) PROC f LPAREN EVAL(EVAL_CAT(INFLATE, PFIX f) ARGS f)

#define APPLY1(f, a0) EVAL(APPLY_AUX(f) a1 RPAREN)
#define APPLY2(f, a0, a1) EVAL(APPLY_AUX(f) a0 COMMA a1 RPAREN)


#define LINTR(m00, m01, m10, m11, vx, vy) { (m00) * (vx) + (m01) * (vy), (m10) * (vx) + (m11) * (vy) }
#define MATRIX(m00, m01, m10, m11) m00, m01, m10, m11
#define ROTATE(theta)  CURRY4(LINTR, cos(theta), -sin(theta), sin(theta), cos(theta))

APPLY2(ROTATE(pi/3), x, y);
==> { (cos(pi/3)) * (x) + (-sin(pi/3)) * (y), (sin(pi/3)) * (x) + (cos(pi/3)) * (y) };

#define REVERSE(x, y, z) z, y, x
APPLY1(CURRY2(REVERSE, 0, 1), 2);
==> 2, 1, 0

今晩の食事は八宝菜です。