もっとちゃんとした 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
今晩の食事は八宝菜です。