Created
May 30, 2021 19:52
-
-
Save hbobenicio/bd18f03847b584dcded0114dac3cfa31 to your computer and use it in GitHub Desktop.
A Result type example for C
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <stdlib.h> | |
#include <assert.h> | |
#include <stdbool.h> | |
#define OUTCOME_SUCCESS 0 | |
typedef double DivResultOk; | |
// TODO For a generic error handling, you coud add a polimorphic interface here. This could help for generec error handling and error chaining. | |
// TODO Downcasting could be a challenge, but still possible. | |
typedef const char* DivResultErr; | |
// Tagged union | |
typedef struct { | |
enum { | |
DIV_OUTCOME_SUCCESS = OUTCOME_SUCCESS, | |
DIV_OUTCOME_ERR_DIV_BY_ZERO, | |
DIV_OUTCOME_ERR_OVERFLOW, | |
DIV_OUTCOME_ERR_OVERFLOW2, | |
// other errors here... | |
} outcome; | |
union { | |
DivResultOk value; | |
DivResultErr err; | |
}; | |
} DivResult; | |
static DivResult divide_by(int x, int y) { | |
if (y == 0) { | |
return (DivResult){ | |
.outcome = DIV_OUTCOME_ERR_DIV_BY_ZERO, | |
.err = "divide_by: cannot divide by zero", | |
}; | |
} | |
if (x > 1000 || y > 1000) { | |
return (DivResult){ | |
.outcome = DIV_OUTCOME_ERR_OVERFLOW2, | |
.err = "divide_by: overflow: numbers too high", | |
}; | |
} | |
return (DivResult){ | |
.outcome = DIV_OUTCOME_SUCCESS, | |
.value = (double) x / y, | |
}; | |
} | |
int main() { | |
{ | |
int x = 10; | |
int y = 0; | |
DivResult result = divide_by(x, y); | |
if (result.outcome != OUTCOME_SUCCESS) { | |
fprintf(stderr, "error: %s\n", result.err); | |
} else { | |
printf("ok: %d / %d == %lf\n", x, y, result.value); | |
} | |
} | |
{ | |
int x = 10; | |
int y = 1001; | |
DivResult result = divide_by(x, y); | |
switch(result.outcome) { | |
case OUTCOME_SUCCESS: | |
// noop | |
break; | |
case DIV_OUTCOME_ERR_DIV_BY_ZERO: | |
case DIV_OUTCOME_ERR_OVERFLOW: | |
fprintf(stderr, "error: %s\n", result.err); | |
break; | |
default: | |
fputs("error: assertion failure: unrecognized error on DivResult outcome.\n", stderr); | |
assert(false); | |
} | |
printf("ok: %d / %d == %lf\n", x, y, result.value); | |
} | |
{ | |
int x = 10; | |
int y = 5; | |
DivResult result = divide_by(x, y); | |
if (result.outcome != OUTCOME_SUCCESS) { | |
fprintf(stderr, "error: %s\n", result.err); | |
} else { | |
printf("ok: %d / %d == %lf\n", x, y, result.value); | |
} | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment