Skip to content

Instantly share code, notes, and snippets.

@io12
Created August 22, 2017 16:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save io12/5be3d6c5ebb54c04b637bc76e9154fcc to your computer and use it in GitHub Desktop.
Save io12/5be3d6c5ebb54c04b637bc76e9154fcc to your computer and use it in GitHub Desktop.
/*
$----------------$
| Example usage: |
$----------------$------------------------------------------------------$
| #include <stdbool.h> |
| #include <stdio.h> |
| |
| #include "func.h" |
| |
| LIST_TYPE(int) |
| |
| bool is_even(const int *x) |
| { return |
| *x % 2 == 0; |
| } |
| |
| int *print_int(const int *x) |
| { return int_dup(( |
| printf("%d\n", *x), x)); |
| } |
| |
| int main(void) |
| { |
| let intList* list = list(int, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10); |
| let intList* filtered_list = int_filter(list, is_even); |
| int_map(filtered_list, print_int); |
| } |
$-----------------------------------------------------------------------$
*/
#ifndef FUNC_H__
#define FUNC_H__
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#define let const
#define list(type, ...) list__(type, ((type[]){ __VA_ARGS__ }))
#define list__(type, arr) \
type##_list__(sizeof(arr[0]), sizeof(arr) / sizeof(arr[0]), arr)
#define LIST_TYPE(type) \
typedef bool type##Predicate(const type *); \
typedef type *type##UnaryFunc(const type *); \
typedef type *type##BinaryFunc(const type *, const type *); \
\
typedef struct type##list type##List; \
\
struct type##list { \
type *head; \
type##List *tail; \
}; \
\
type *type##_dup(const type *t); \
type##List *type##_list__(const size_t size, const size_t nmemb, \
const type arr[]); \
type##List *type##_prepend(type *head, type##List *tail); \
type##List *type##_map(const type##List *list, type##UnaryFunc *func); \
type##List *type##_filter(const type##List *list, type##Predicate *func); \
type *type##_reduce(const type##List *list, type##BinaryFunc *func); \
\
inline type *type##_dup(const type *t) \
{ return \
memcpy(malloc(sizeof(type)), t, sizeof(type)); \
} \
\
inline type##List *type##_list__(const size_t size, const size_t nmemb, \
const type arr[]) \
{ return \
nmemb == 0 \
? NULL \
: type##_prepend(type##_dup(arr), \
type##_list__(size, nmemb - 1, arr + 1)); \
} \
\
inline type##List *type##_prepend(type *head, type##List *tail) \
{ \
type##List * const super = malloc(sizeof(type##List)); \
super->head = head; \
super->tail = tail; \
return super; \
} \
\
inline type##List *type##_map(const type##List *list, type##UnaryFunc *func) \
{ return \
list == NULL \
? NULL \
: type##_prepend(func(list->head), type##_map(list->tail, func)); \
} \
\
inline type##List *type##_filter(const type##List *list, type##Predicate *func) \
{ return \
list == NULL \
? NULL \
: func(list->head) \
? type##_prepend(list->head, type##_filter(list->tail, func)) \
: type##_filter(list->tail, func); \
} \
\
inline type *type##_reduce(const type##List *list, type##BinaryFunc *func) \
{ return \
list->tail == NULL \
? list->head \
: func(list->head, type##_reduce(list->tail, func)); \
}
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment