├── .gitignore ├── Makefile ├── README.md ├── LICENSE ├── reverse.c └── mergesort.c /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.bak -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: all clean 2 | 3 | CC = gcc 4 | CFLAGS = -O0 -g -Wall -Werror -std=gnu99 5 | 6 | all: reverse mergesort 7 | 8 | reverse: reverse.o 9 | 10 | mergesort: mergesort.o 11 | 12 | clean: 13 | rm -f *.o reverse mergesort 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Functional-Programming-in-C 2 | https://hackmd.io/s/r1SgsdF3X 3 | 4 | ## References 5 | 6 | ### merge sort (linked list) 7 | * https://www.geeksforgeeks.org/merge-sort-for-linked-list/ 8 | 9 | ### list.h 10 | * https://github.com/sysprog21/linux-list/blob/master/include/list.h 11 | * https://hackmd.io/SqNCmZ8HSYegTCQZ0sQKZw -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Vincent Chen 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /reverse.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | /* integer linked list type */ 6 | typedef struct __int_list const *const int_list_t; 7 | static int_list_t const Nil = NULL; /* empty list */ 8 | 9 | /* singly linked list element */ 10 | typedef struct __int_list { 11 | int_list_t next; 12 | int32_t const val; 13 | } node_t; 14 | 15 | /* A pointer to where we are about to store the result of computation */ 16 | typedef void *const CPS_Result; 17 | 18 | /* prototypes for the continuations */ 19 | typedef void (*MakeListCallback)(int_list_t list, CPS_Result res); 20 | void make_list(uint32_t const arr_size, 21 | int32_t const array[], 22 | int_list_t lst, 23 | MakeListCallback const cb, 24 | CPS_Result res); 25 | 26 | typedef void (*ReversedListCallback)(int_list_t rlist, CPS_Result res); 27 | void reverse(int_list_t list, 28 | int_list_t rlist, 29 | ReversedListCallback const cb, 30 | CPS_Result res); 31 | 32 | typedef void (*VoidMappable)(int32_t const val); 33 | void void_map_array(VoidMappable const cb, 34 | uint32_t const size, 35 | int32_t const *const arr); 36 | 37 | void list2array(int_list_t list, CPS_Result res); 38 | 39 | /* reverse a list and then store it in an array */ 40 | void reverse_toarray(int_list_t list, CPS_Result res) { 41 | reverse(list, Nil, list2array, res); 42 | } 43 | 44 | static void print_val(int32_t const val) { printf("%d ", val); } 45 | 46 | #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0])) 47 | 48 | int main(int argc, char *argv[]) { 49 | int32_t arr[] = {99, 95, 90, 85, 80, 20, 75, 15, 10, 5}; 50 | uint32_t const arr_size = ARRAY_SIZE(arr); 51 | 52 | int32_t res[arr_size]; 53 | /* call make_list and pass reverse_toarray as the "continuation" */ 54 | make_list(arr_size, arr, Nil, reverse_toarray, res); 55 | 56 | /* print out the reversed array */ 57 | void_map_array(print_val, arr_size, res); 58 | printf("\n"); 59 | return 0; 60 | } 61 | 62 | /* construct a linked list from an array */ 63 | void make_list(uint32_t const arr_size, 64 | int32_t const arr[], 65 | int_list_t lst, 66 | MakeListCallback const cb, 67 | CPS_Result res) { 68 | if (!arr_size) { 69 | cb(lst, res); 70 | return; 71 | } 72 | make_list(arr_size - 1, arr, 73 | &(node_t){.val = arr[arr_size - 1], .next = lst}, cb, res); 74 | } 75 | 76 | /* transform a linked list into an array */ 77 | void list2array(int_list_t list, CPS_Result res) { 78 | if (Nil == list) 79 | return; 80 | int32_t *array = res; 81 | array[0] = list->val; 82 | list2array(list->next, array + 1); 83 | } 84 | 85 | void reverse(int_list_t list, 86 | int_list_t rlist, /* reversed list */ 87 | ReversedListCallback const cb, 88 | CPS_Result res) { 89 | if (Nil == list) { 90 | cb(rlist, res); 91 | return; 92 | } 93 | reverse(list->next, &(node_t) {.val = list->val, .next = rlist}, cb, res); 94 | } 95 | 96 | /* iterate over an array and performs action cb on each element */ 97 | void void_map_array(VoidMappable const cb, 98 | uint32_t const size, 99 | int32_t const *const arr) { 100 | if (!size) 101 | return; 102 | cb(arr[0]); 103 | void_map_array(cb, size - 1, arr + 1); 104 | } -------------------------------------------------------------------------------- /mergesort.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #define container_of(ptr, type, member) \ 7 | ((type *) ((char *) (ptr) -offsetof(type, member))) 8 | 9 | #define list_entry(node, type, member) container_of(node, type, member) 10 | 11 | typedef struct __list * list_t; 12 | typedef struct __list { 13 | list_t next; 14 | } node_t; 15 | 16 | typedef struct __ele { 17 | int32_t const val; 18 | list_t const list; 19 | } ele_t; 20 | 21 | static const ele_t Nil = {.val = 0, .list = &(node_t){ .next = NULL }}; 22 | 23 | typedef void *const CPS_Result; 24 | typedef void (*MakeListCallback)(ele_t *e, CPS_Result res); 25 | void make_list(uint32_t const arr_size, 26 | int32_t const array[], 27 | ele_t *e, 28 | MakeListCallback const cb, 29 | CPS_Result res); 30 | 31 | void mergesort_toarray(ele_t *e, CPS_Result res); 32 | 33 | /* Merge sort */ 34 | void mergesort(ele_t **source); 35 | void partition(ele_t *head, ele_t **front, ele_t **back); 36 | ele_t *mergeLists(ele_t *a, ele_t *b); 37 | 38 | typedef void (*VoidMappable)(int32_t const val); 39 | void void_map_array(VoidMappable const cb, 40 | uint32_t const size, 41 | int32_t const *const arr); 42 | 43 | void list2array(ele_t *e, CPS_Result res); 44 | 45 | static void print_val(int32_t const val) { printf("%d ", val); } 46 | 47 | #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0])) 48 | 49 | int main(int argc, char *argv[]) { 50 | int32_t arr[] = {99, 95, 90, 85, 80, 20, 75, 15, 10, 5}; 51 | uint32_t const arr_size = ARRAY_SIZE(arr); 52 | 53 | int32_t res[arr_size]; 54 | make_list(arr_size, arr, (ele_t *)(&Nil), mergesort_toarray, res); 55 | 56 | void_map_array(print_val, arr_size, res); 57 | printf("\n"); 58 | return 0; 59 | } 60 | 61 | void make_list(uint32_t const arr_size, 62 | int32_t const arr[], 63 | ele_t *e, 64 | MakeListCallback const cb, 65 | CPS_Result res) { 66 | if (!arr_size) { 67 | cb(e, res); 68 | return; 69 | } 70 | 71 | make_list(arr_size - 1, arr, 72 | &(ele_t){ 73 | .val = arr[arr_size - 1], 74 | .list = &(node_t){ .next = (list_t)(&(e->list)) } 75 | }, 76 | cb, res); 77 | } 78 | 79 | void list2array(ele_t *e, CPS_Result res) { 80 | if (e->list->next == NULL) { 81 | return; 82 | } 83 | int32_t *array = res; 84 | array[0] = e->val; 85 | list2array(list_entry(e->list->next, ele_t, list), array + 1); 86 | } 87 | 88 | void mergesort_toarray(ele_t *e, CPS_Result res) { 89 | if (e->list->next != NULL) 90 | mergesort(&e); 91 | list2array(e, res); 92 | } 93 | 94 | void void_map_array(VoidMappable const cb, 95 | uint32_t const size, 96 | int32_t const *const arr) { 97 | if (!size) 98 | return; 99 | cb(arr[0]); 100 | void_map_array(cb, size - 1, arr + 1); 101 | } 102 | 103 | /* Merge sort */ 104 | void mergesort(ele_t **source) { 105 | ele_t *head = *source; 106 | ele_t *a = NULL; 107 | ele_t *b = NULL; 108 | 109 | if (head == NULL || head->list->next == (list_t)(&(Nil.list))) 110 | return; 111 | 112 | partition(head, &a, &b); 113 | 114 | mergesort(&a); 115 | mergesort(&b); 116 | 117 | *source = mergeLists(a, b); 118 | } 119 | 120 | void partition(ele_t *head, ele_t **front, ele_t **back) { 121 | 122 | ele_t *fast; 123 | ele_t *slow; 124 | 125 | if (head == NULL || head->list->next == (list_t)(&(Nil.list))) { 126 | *front = head; 127 | *back = NULL; 128 | } 129 | else { 130 | slow = head; 131 | fast = list_entry(head->list->next, ele_t, list); 132 | 133 | while(fast->list->next != NULL) { 134 | 135 | fast = list_entry(fast->list->next, ele_t, list); 136 | 137 | if (fast->list->next != NULL) { 138 | slow = list_entry(slow->list->next, ele_t, list); 139 | fast = list_entry(fast->list->next, ele_t, list); 140 | } 141 | } 142 | 143 | *front = head; 144 | *back = list_entry(slow->list->next, ele_t, list); 145 | slow->list->next = (list_t)(&(Nil.list)); 146 | } 147 | 148 | } 149 | 150 | ele_t *mergeLists(ele_t *a, ele_t *b) { 151 | ele_t *mergedList = NULL; 152 | ele_t *tmp; 153 | 154 | if (a->list->next == NULL) { 155 | return b; 156 | } 157 | else if (b->list->next == NULL) { 158 | return a; 159 | } 160 | 161 | if (a->val <= b->val) { 162 | mergedList = a; 163 | tmp = mergeLists(list_entry(a->list->next, ele_t, list), b); 164 | mergedList->list->next = (list_t)(&(tmp->list)); 165 | } 166 | else { 167 | mergedList = b; 168 | tmp = mergeLists(a, list_entry(b->list->next, ele_t, list)); 169 | mergedList->list->next = (list_t)(&(tmp->list)); 170 | } 171 | 172 | return mergedList; 173 | } --------------------------------------------------------------------------------