Skip to content

Instantly share code, notes, and snippets.

@GalileoCap
Last active April 8, 2025 23:07
Show Gist options
  • Save GalileoCap/f662169062b5c6b5e006abba69c0704b to your computer and use it in GitHub Desktop.
Save GalileoCap/f662169062b5c6b5e006abba69c0704b to your computer and use it in GitHub Desktop.
Rust's Option<T> and Result<T, E> implemented in C
#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;
}
#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