Last active
April 8, 2025 23:07
-
-
Save GalileoCap/f662169062b5c6b5e006abba69c0704b to your computer and use it in GitHub Desktop.
Rust's Option<T> and Result<T, E> implemented in 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> | |
#define Option_t(T) struct option__ ## T | |
#define Option_td(T) \ | |
Option_t(T) { \ | |
char some; \ | |
T value; \ | |
} | |
#define None(T) \ | |
((Option_t(T)){.some = 0}) | |
#define Some(T, v) \ | |
((Option_t(T)){.some = 1, .value = v}) | |
#define try_option(T, r) \ | |
({ \ | |
typeof(r) r_ = (r); \ | |
if (!r_.some) \ | |
return None(T); \ | |
(r_).value; \ | |
}) | |
char b2c(char b) | |
{ | |
if (b) | |
return 'T'; | |
else | |
return 'F'; | |
} | |
Option_td(int); | |
Option_t(int) divide(int x, int y) | |
{ | |
if (y != 0) | |
return Some(int, x / y); | |
else | |
return None(int); | |
} | |
Option_td(char); | |
Option_t(char) divide_by_zero(int x) | |
{ | |
Option_t(int) r = divide(x, 0); | |
int f = try_option(char, r); | |
return Some(char, f + '0'); | |
/*return Ok(char, try_result(char, r) + '0');*/ | |
} | |
Option_t(char) divide_by_two(int x) | |
{ | |
return Some(char, try_option(char, divide(x, 2)) + '0'); | |
} | |
int main(void) | |
{ | |
Option_t(char) z = divide_by_zero(6); | |
printf("Divide by zero: %c %c\n", b2c(z.some), z.value); | |
Option_t(char) t = divide_by_two(6); | |
printf("Divide by two: %c %c\n", b2c(t.some), t.value); | |
return 0; | |
} |
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> | |
#define __Result_t(T, E) struct result__ ## T ## __ ## E | |
#define _Result_t(T, E) __Result_t(T, E) | |
#define _Result_td(T, E) \ | |
_Result_t(T, E) { \ | |
char success; \ | |
union { \ | |
T result; \ | |
E error; \ | |
}; \ | |
} | |
#define _Err(T, E, e) \ | |
((_Result_t(T, E)){.success = 0, .error = e}) | |
#define _Ok(T, E, r) \ | |
((_Result_t(T, E)){.success = 1, .result = r}) | |
#define _try_result(T, E, r) \ | |
({ \ | |
typeof(r) r_ = (r); \ | |
if (!r_.success) \ | |
return _Err(T, E, r_.error); \ | |
r_.result; \ | |
}) | |
#ifndef RESULT_ERR_T | |
#define RESULT_ERR_T short | |
#endif // !RESULT_ERR_T | |
#define Result_t(T) _Result_t(T, RESULT_ERR_T) | |
#define Result_td(T) _Result_td(T, RESULT_ERR_T) | |
#define Err(T, e) _Err(T, RESULT_ERR_T, e) | |
#define Ok(T, r) _Ok(T, RESULT_ERR_T, r) | |
#define try_result(T, r) _try_result(T, RESULT_ERR_T, r) | |
char b2c(char b) | |
{ | |
if (b) | |
return 'T'; | |
else | |
return 'F'; | |
} | |
Result_td(int); | |
Result_t(int) divide(int x, int y) | |
{ | |
if (y != 0) | |
return Ok(int, x / y); | |
else | |
return Err(int, -1); | |
} | |
Result_td(char); | |
Result_t(char) divide_by_zero(int x) | |
{ | |
Result_t(int) r = divide(x, 0); | |
int f = try_result(char, r); | |
return Ok(char, f + '0'); | |
/*return Ok(char, try_result(char, r) + '0');*/ | |
} | |
Result_t(char) divide_by_two(int x) | |
{ | |
return Ok(char, try_result(char, divide(x, 2)) + '0'); | |
} | |
int main(void) | |
{ | |
Result_t(char) z = divide_by_zero(6); | |
printf("Divide by zero: %c %c %c\n", b2c(z.success), z.result, z.error); | |
Result_t(char) t = divide_by_two(6); | |
printf("Divide by two: %c %c %c\n", b2c(t.success), t.result, t.error); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment