ダメな例
GCC 拡張が楽しかったので調子に乗っていたら、「こういうプログラムを書いてはいけません」の見本みたいになってしまった。
ちょっと長いので続きで。
一応、汎用のリストもどき(配列はダメ)で、要素の読み書きは静的に型検査できる。いや、逆に言えばその程度しかできないわけです。どうにかして汎用の関数とかを書けないもんでしょうか…。あと、クロージャ。うーむ。
#include <stdlib.h> #include <stdio.h> #define list(type) _list_##type #define declare_list_of(type) \ typedef struct list(type) { \ struct list(type) *_cdr; type _car; \ } *list(type) #define cons(car, cdr) ({ \ typeof(cdr) _c = malloc(sizeof(*_c)); \ _c->_car = (car); _c->_cdr = (cdr); _c; \ }) #define car(list) ((list)->_car) #define cdr(list) ((list)->_cdr) #define nil(type) ((list(type))NULL) #define iter(list, ...) ({ \ void _f(typeof(car(list)) it) { __VA_ARGS__; } \ for (typeof(list) _c = (list); _c; _c = cdr(_c)) _f(car(_c)); \ }) #define fold(list, init, ...) ({ \ typeof(init) _a = (init); \ typeof(_a) _f(typeof(_a) acc, typeof(car(list)) it) { \ return ({ __VA_ARGS__; }); \ } \ for (typeof(list) _c = (list); _c; _c = cdr(_c)) _a = _f(_a, car(_c)); \ _a; \ }) int main() { typedef char *string; declare_list_of(string); declare_list_of(double); list(string) one_to_three; int n = 0; one_to_three = cons("one", cons("two", cons("three", nil(string)))); iter(one_to_three, printf("%s -> %d\n", it, ++n)); list(double) one_to_ten = NULL; for (int x = 10; x >= 1; x--) one_to_ten = cons(x, one_to_ten); printf("10! = %f\n", fold(one_to_ten, 1.0, printf("%f\n", acc), acc * it)); return 0; }