#ifndef LIST_H_ #define LIST_H_ /* ----- List definition ----- */ #ifndef LIST_IMPLEMENTATION #define DefList(type) \ struct Node##type { \ type head; \ struct Node##type* rest; \ }; \ typedef struct Node##type* List##type; \ void List##type##_deinit(List##type list); \ type List##type##_car(struct Node##type node); \ struct Node##type* List##type##_cdr(struct Node##type node); \ List##type List##type##_cons(type a, List##type list); \ List##type List##type##_rev(List##type list, List##type a); \ List##type List##type##_reverse(List##type list); \ size_t List##type##_length(List##type list); \ type List##type##_at(List##type list, size_t index); #else #define DefList(type) \ struct Node##type { \ type head; \ struct Node##type* rest; \ }; \ typedef struct Node##type* List##type; \ \ void List##type##_deinit(List##type list) { \ if (list != NULL) { \ List##type##_deinit(list->rest); \ assert(list->rest == NULL); \ free(list); \ list = NULL; \ } \ } \ \ type List##type##_car(struct Node##type node) { \ List##type##_deinit(node.rest); \ return node.head; \ } \ \ struct Node##type* List##type##_cdr(struct Node##type node) { \ return node.rest; \ } \ \ List##type List##type##_cons(type a, List##type list) { \ struct Node##type* node = (struct Node##type*)calloc(sizeof(struct Node##type), 1); \ exists(node); \ *node = (struct Node##type){ .head = a, .rest = list }; \ return (List##type)node; \ } \ \ List##type List##type##_rev(List##type list, List##type a) { \ if (list != NULL) return List##type##_rev(list->rest, List##type##_cons(list->head, a)); \ else return a; \ } \ \ List##type List##type##_reverse(List##type list) { \ return List##type##_rev(list, NULL); \ } \ \ size_t List##type##_length(List##type list) { \ if (list != NULL) return List##type##_length(list->rest) + 1; \ else return 0; \ } \ \ type List##type##_at(List##type list, size_t index) { \ if (list != NULL) return index == 1 ? list->head : List##type##_at(list->rest, index - 1); \ else exists(NULL); \ return (type){0}; \ } #endif #endif // LIST_H_