ダメな例

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;
}

コンパイルgcc -std=gnu99 で。