#ifndef __cplusplus # define decltype typeof # include #endif #include #include #include #define TOKEN_CONCAT_EX(x, y) x##y #define TOKEN_CONCAT(x, y) TOKEN_CONCAT_EX(x, y) #define UNIQUIFY(x) TOKEN_CONCAT(x, __LINE__) #define Result_EX(T, E) result_##T##_##E##_t #define Result(T, E) Result_EX(T, E) #define ResultDecl(T, E) \ typedef struct \ { \ bool _is_ok; \ union \ { \ T _ok; \ E _err; \ }; \ } Result(T, E) #define Ok(V, T, E) \ ((Result(T, E)){ \ ._is_ok = true, \ ._ok = V, \ }) #define Err(V, T, E) \ ((Result(T, E)){ \ ._is_ok = false, \ ._err = V, \ }) #define is_ok(V) (V._is_ok) #define is_err(V) (!(V._is_ok)) #define if_let_Ok(I, V) \ if (is_ok(V)) \ for (bool UNIQUIFY(once) = true; UNIQUIFY(once);) \ for (decltype(V._ok) I = V._ok; UNIQUIFY(once); UNIQUIFY(once) = false) #define if_let_Err(I, V) \ if (is_err(V)) \ for (bool UNIQUIFY(once) = true; UNIQUIFY(once);) \ for (decltype(V._err) I = V._err; UNIQUIFY(once); UNIQUIFY(once) = false) #define unwrap(V) ((is_ok(V) ? (void)0 : abort()), V._ok) #define unwrap_err(V) ((is_err(V) ? (void)0 : abort()), V._err) #define get_ok(V) (is_ok(V) ? &(V._ok) : nullptr) #define get_err(V) (is_err(V) ? &(V._err) : nullptr) #define map(V, T, E, F) (is_ok(V) ? Ok(F(V._ok), T, E) : Err(V._err, T, E)) #define map_err(V, T, E, F) \ (is_err(V) ? Ok(V._ok, T, E) : Err(F(V._err), T, E)) #define and_then(V, T, E, F) (is_ok(V) ? F(V._ok) : Err(V._err, T, E)) #define or_else(V, T, E, F) (is_ok(V) ? Ok(V._ok, T, E) : F(V._err)) #define flatten(V, T, E) \ (is_ok(V) ? (is_ok(V._ok) ? Ok(V._ok._ok, T, E) : Err(V._ok._err, T, E)) \ : Err(V._err, T, E)) typedef struct { int val; } thing_t; ResultDecl(int, bool); ResultDecl(thing_t, bool); ResultDecl(Result(thing_t, bool), bool); thing_t make_thing(int v) { return (thing_t){.val = v}; } Result(thing_t, bool) maybe_make_thing(int v) { if (v % 200 == 0) return Err(v == 200, thing_t, bool); else return Ok(make_thing(v), thing_t, bool); } Result(int, bool) test(bool v, int i) { if (v || i == 0) return Err(v, int, bool); else return Ok(i, int, bool); } int main() { int input1, input2; fscanf(stdin, "%d %d", &input1, &input2); Result(int, bool) result = test(input1 != 20, input2); if_let_Ok(ok, result) { fprintf(stdout, "%d\n", ok); } else if_let_Err(err, result) { fprintf(stderr, "%s\n", err ? "true" : "false"); } Result(thing_t, bool) thing = map(result, thing_t, bool, make_thing); if_let_Ok(ok, thing) { fprintf(stdout, "we got a thing %d\n", ok.val); } Result(Result(thing_t, bool), bool) maybe_thing = map(result, Result(thing_t, bool), boo, maybe_make_thing); Result(thing_t, bool) flattened = flatten(maybe_thing, thing_t, bool); if_let_Ok(ok, flattened) { fprintf(stdout, "we got a flattened thing %d\n", ok.val); } Result(thing_t, bool) and_thend = and_then(result, thing_t, bool, maybe_make_thing); if_let_Ok(ok, and_thend) { fprintf(stdout, "we got an and_then'd thing %d\n", ok.val); } }