Skip to content

Instantly share code, notes, and snippets.

@dreamsmasher
Created October 2, 2022 00:16
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dreamsmasher/067ff9f124902f52cb2dcea69686e4a3 to your computer and use it in GitHub Desktop.
Save dreamsmasher/067ff9f124902f52cb2dcea69686e4a3 to your computer and use it in GitHub Desktop.
Function Overloading in Rust
#![feature(fn_traits, unboxed_closures)]
macro_rules! orelse {
(($($lhs:tt)+), $rhs:tt) => {$($lhs)+};
((), ($($rhs:tt)*)) => {$($rhs)*}
}
macro_rules! overload {
(
$v:vis fn $fn_name:ident {
$(
$(<$($param:tt $(: $constraint:ty)?),* $(,)*>)? ($($name:ident : $typ:ty),* $(,)*) $(-> $out_ty:ty)? {
$($body:tt)*
}
),+ $(,)*
}
) => {
#[allow(non_camel_case_types)]
#[derive(Clone, Copy, Debug)]
$v struct $fn_name;
$(
impl $(< $($param $(: $constraint)?,)*>)? FnOnce<($($typ,)*)> for $fn_name {
type Output = orelse!{($($out_ty)?), ( () )};
extern "rust-call" fn call_once(self, args: ($($typ,)*)) -> Self::Output {
let ($($name,)*) = args;
$($body)*
}
}
impl $(< $($param $(: $constraint)?,)*>)? FnMut<($($typ,)*)> for $fn_name {
extern "rust-call" fn call_mut(&mut self, args: ($($typ,)*)) -> <Self as FnOnce<($($typ,)*)>>::Output {
self.clone().call_once(args)
}
}
impl $(< $($param $(: $constraint)?,)*>)? Fn<($($typ,)*)> for $fn_name {
extern "rust-call" fn call(&self, args: ($($typ,)*)) -> <Self as FnOnce<($($typ,)*)>>::Output {
self.clone().call_once(args)
}
}
)+
}
}
overload! {
pub fn foo {
(x: i32) -> i64 {
x as i64
},
(xs: Vec<i32>) -> usize {
xs.into_iter()
.map(foo)
.sum::<i64>() as usize
},
<'a>(a: Vec<i32>, _b: (), c: Option<&'a str>) -> (Vec<i32>, (), &'a str) {
let a = a.into_iter().map(|x| x * 2).collect();
(a, (), c.unwrap_or("hewwo :3"))
},
(some_float: f64) {
println!("{}", some_float)
}
}
}
fn main() {
let f0: i64 = foo(0);
assert_eq!(f0, 0);
let f1: usize = foo(vec![1, 2, 3, 4]);
assert_eq!(f1, 10);
let (i32s, unit, s) = foo(vec![4,5,6], (), Some("heheheheh"));
assert_eq!(i32s, vec![8, 10, 12]);
assert_eq!(unit, ());
assert_eq!(s, "heheheheh");
foo(69.420);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment