Advertisement
alexeyshmalko

Maybe Monad in C

Sep 15th, 2015
877
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 3.23 KB | None | 0 0
  1. #include <stdio.h>
  2.  
  3. #define PP_NARG(...) \
  4.          PP_NARG_(__VA_ARGS__,PP_RSEQ_N())
  5. #define PP_NARG_(...) \
  6.          PP_ARG_N(__VA_ARGS__)
  7. #define PP_ARG_N( \
  8.           _1, _2, _3, _4, _5, _6, _7, _8, _9,_10, \
  9.          _11,_12,_13,_14,_15,_16,_17,_18,_19,_20, \
  10.          _21,_22,_23,_24,_25,_26,_27,_28,_29,_30, \
  11.          _31,_32,_33,_34,_35,_36,_37,_38,_39,_40, \
  12.          _41,_42,_43,_44,_45,_46,_47,_48,_49,_50, \
  13.          _51,_52,_53,_54,_55,_56,_57,_58,_59,_60, \
  14.          _61,_62,_63,N,...) N
  15. #define PP_RSEQ_N() \
  16.          63,62,61,60,                   \
  17.          59,58,57,56,55,54,53,52,51,50, \
  18.          49,48,47,46,45,44,43,42,41,40, \
  19.          39,38,37,36,35,34,33,32,31,30, \
  20.          29,28,27,26,25,24,23,22,21,20, \
  21.          19,18,17,16,15,14,13,12,11,10, \
  22.          9,8,7,6,5,4,3,2,1,0
  23.  
  24. #define CAT(a, ...) PRIMITIVE_CAT(a, __VA_ARGS__)
  25. #define PRIMITIVE_CAT(a, ...) a ## __VA_ARGS__
  26.  
  27. #define IIF(c) PRIMITIVE_CAT(IIF_, c)
  28. #define IIF_0(t, ...) __VA_ARGS__
  29. #define IIF_1(t, ...) t
  30.  
  31. #define COMPL(b) PRIMITIVE_CAT(COMPL_, b)
  32. #define COMPL_0 1
  33. #define COMPL_1 0
  34.  
  35. #define INC(x) PRIMITIVE_CAT(INC_, x)
  36. #define INC_0 1
  37. #define INC_1 2
  38. #define INC_2 3
  39. #define INC_3 4
  40. #define INC_4 5
  41. #define INC_5 6
  42. #define INC_6 7
  43. #define INC_7 8
  44. #define INC_8 9
  45. #define INC_9 9
  46.  
  47. #define DEC(x) PRIMITIVE_CAT(DEC_, x)
  48. #define DEC_0 0
  49. #define DEC_1 0
  50. #define DEC_2 1
  51. #define DEC_3 2
  52. #define DEC_4 3
  53. #define DEC_5 4
  54. #define DEC_6 5
  55. #define DEC_7 6
  56. #define DEC_8 7
  57. #define DEC_9 8
  58.  
  59. #define CHECK_N(x, n, ...) n
  60. #define CHECK(...) CHECK_N(__VA_ARGS__, 0,)
  61. #define PROBE(x) x, 1,
  62.  
  63. #define NOT(x) CHECK(PRIMITIVE_CAT(NOT_, x))
  64. #define NOT_0 PROBE(~)
  65.  
  66. #define BOOL(x) COMPL(NOT(x))
  67. #define IF(c) IIF(BOOL(c))
  68.  
  69. #define EAT(...)
  70. #define EXPAND(...) __VA_ARGS__
  71. #define WHEN(c) IF(c)(EXPAND, EAT)
  72.  
  73. #define EMPTY()
  74. #define DEFER(id) id EMPTY()
  75. #define OBSTRUCT(...) __VA_ARGS__ DEFER(EMPTY)()
  76. #define EXPAND(...) __VA_ARGS__
  77.  
  78. #define EVAL(...)  EVAL1(EVAL1(EVAL1(__VA_ARGS__)))
  79. #define EVAL1(...) EVAL2(EVAL2(EVAL2(__VA_ARGS__)))
  80. #define EVAL2(...) EVAL3(EVAL3(EVAL3(__VA_ARGS__)))
  81. #define EVAL3(...) EVAL4(EVAL4(EVAL4(__VA_ARGS__)))
  82. #define EVAL4(...) EVAL5(EVAL5(EVAL5(__VA_ARGS__)))
  83. #define EVAL5(...) __VA_ARGS__
  84.  
  85. #define MAYBE_BIND(count, condition, x1, x2, ...) ({ \
  86.         typeof(x1) __res0 = (x1); \
  87.         condition(__res0) ? __res0 : \
  88.             IF(count) \
  89.             ( \
  90.                 OBSTRUCT(MAYBE_BIND_INDIRECT) () \
  91.                 ( \
  92.                     DEC(count), condition, x2, __VA_ARGS__ \
  93.                 ), \
  94.                 (x2) \
  95.             ) \
  96.         ; \
  97.     })
  98.  
  99. #define MAYBE_BIND_INDIRECT() MAYBE_BIND
  100.  
  101. #define MAYBE(condition, x1, ...) (EVAL(MAYBE_BIND(DEC(PP_NARG(__VA_ARGS__)), condition, x1, __VA_ARGS__)))
  102.  
  103. #define IS_ERROR(x) ((x) < 0)
  104.  
  105. int f1() {
  106.     printf("f1()\n");
  107.     return 0;
  108. }
  109. int f2() {
  110.     printf("f2()\n");
  111.     return -1;
  112. }
  113. int f3() {
  114.     printf("f3()\n");
  115.     return 2;
  116. }
  117. int f4() {
  118.     printf("f4()\n");
  119.     return 5;
  120. }
  121.  
  122. int main(void) {
  123.  
  124.     int res = MAYBE(IS_ERROR,
  125.             f1(),
  126.             f2(),
  127.             f3(),
  128.             f4()
  129.         );
  130.     printf("res = %i\n\n", res);
  131.     // f1()
  132.     // f2()
  133.     // res = -1
  134.  
  135.     int a, b, c;
  136.     res = MAYBE(IS_ERROR,
  137.             a = f1(),
  138.             b = f3(),
  139.             c = f4(),
  140.             a + b + c
  141.         );
  142.     printf("res = %i\n", res);
  143.     // f1()
  144.     // f3()
  145.     // f4()
  146.     // res = 7
  147.    
  148.     return 0;
  149. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement