-
-
Save machuidel/d7cc099ddc4970c6ddf4 to your computer and use it in GitHub Desktop.
#pragma once | |
#ifndef _XOPTION_TYPE_H_ | |
#define _XOPTION_TYPE_H_ | |
#ifdef __cplusplus | |
extern "C" | |
{ | |
#endif | |
#include<stdio.h> | |
#include<stdlib.h> | |
/* Option */ | |
typedef enum { | |
Option_some, | |
Option_none | |
} option_status_t; | |
#define Func_name(out_type, name, ...) name | |
#define Func_out_type(out_type, name, ...) out_type | |
#define Option(type) option ## _ ## type ## _t | |
#define Option_define(type) \ | |
typedef struct { \ | |
option_status_t status; \ | |
type value; \ | |
} Option(type) | |
#define Option_unwrap(x) (x.value) | |
#define Option_flatten(x) Option_unwrap(x) | |
#define Option_is_some(x) (x.status == Option_some) | |
#define Option_is_none(x) (x.status == Option_none) | |
#define Option_none(type) ((Option(type)){Option_none, 0}) | |
#define Option_some(type, value) ((Option(type)){Option_some, value}) | |
/* cmap can be used with stdc functions, but you need to specify the type */ | |
#define Option_cmap(type, f, x) ((Option_is_some(x)) ? Option_some(type, f(x.value)) : Option_none(type)) | |
/* fmap can only be used with an abstract X macro in which you define the type and stdc function */ | |
#define Option_fmap(f, x) Option_cmap(f(Func_out_type), f(Func_name), x) | |
/* cflatmap can be used with stdc functions, but you need to specify the type */ | |
#define Option_cflatmap(type, f, x) Option_flatten(Option_cmap(type, f, x)) | |
/* fflatmap can only be used with an abstract X macro in which you define the type and stdc function */ | |
#define Option_fflatmap(f, x) Option_cflatmap(f(Func_out_type), f(Func_name), x) | |
#ifdef __cplusplus | |
} | |
#endif | |
#endif // _XOPTION_TYPE_H_ |
#include <stdio.h> | |
#include <stdlib.h> | |
#include "option_type.h" | |
/* Define option */ | |
Option_define(float); | |
Option_define(Option(float)); | |
/* Define functions */ | |
float _add2(float x) { | |
return x + 2.0f; | |
} | |
#define add2(_) _(float, _add2) | |
float _mul4(float x) { | |
return x * 4.0f; | |
} | |
#define mul4(_) _(float, _mul4) | |
Option(float) _madd2(float x) { | |
return Option_some(float, x + 2.0f); | |
} | |
#define madd2(_) _(Option(float), _madd2) | |
Option(float) _mmul4(float x) { | |
return Option_some(float, x * 4.0f); | |
} | |
#define mmul4(_) _(Option(float), _mmul4) | |
/* Test routine */ | |
int main(int argc, char **argv) { | |
Option(float) result1 = Option_some(float, 2.0f); | |
Option(float) result2 = Option_fmap(mul4, Option_fmap(add2, result1)); | |
Option(float) result3 = Option_some(float, 2.0f); | |
Option(float) result4 = Option_fflatmap(mmul4, Option_fflatmap(madd2, result3)); | |
if(Option_is_some(result2)) { | |
printf("MAP: Some(%f)\n", Option_unwrap(result2)); | |
} else { | |
printf("MAP: None\n"); | |
} | |
if(Option_is_some(result4)) { | |
printf("FLATMAP: Some(%f)\n", Option_unwrap(result4)); | |
} else { | |
printf("FLATMAP: None\n"); | |
} | |
exit(EXIT_SUCCESS); | |
} |
I would like to work with you on continuing this implementation. I would like to align your Macro's style and convention with the one used by Daan from Microsoft here:
https://github.com/koka-lang/libhandlerPlease contact me if you are interested.
The goals also include implementing a Result type to Mimic Rust's as well, and then couple it all with libhandler (referenced above).
I noticed your comment just now after a year. Libhandler seems like an interesting project. Did you already finish the implementation / changes you mentioned? I did not continue this way I did above. My idea was to create a functional / higher order programming library in C to generate code for my game engine which I figured would be possible with a lot of C preprocessor hackery. Instead I now generate code using a code generator I wrote that reads annotation attributes from the C code using libclang and transform scripts written in Lua. Will release this and several other projects (cross platform build system using Lua etc.) as open source soon.
I would like to work with you on continuing this implementation. I would like to align your Macro's style and convention with the one used by Daan from Microsoft here:
https://github.com/koka-lang/libhandler
Please contact me if you are interested.
The goals also include implementing a Result type to Mimic Rust's as well, and then couple it all with libhandler (referenced above).