Skip to content

Instantly share code, notes, and snippets.

@Sgeo
Last active August 29, 2015 14:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Sgeo/ee7ce70ad91cad0d11bd to your computer and use it in GitHub Desktop.
Save Sgeo/ee7ce70ad91cad0d11bd to your computer and use it in GitHub Desktop.
Functions that convert between pure-style (A -> A) and mutating (&mut A -> ()) functions.
fn mut_to_pure<'f, A, FI>(mut f: FI) -> Box<FnMut(A) -> A+'f>
where FI: FnMut(&mut A)+'f {
Box::new(move |mut a| {f(&mut a); a})
}
fn pure_to_mut<'f, A, FI>(mut f: FI) -> Box<FnMut(&mut A)+'f>
where FI: FnMut(A) -> A+'f {
Box::new(move |a: &mut A| {
unsafe {
let mut temp: A = std::mem::uninitialized();
std::mem::swap(a, &mut temp); // a now contains garbage, temp contains value in question
let mut temp = f(temp);
std::mem::swap(a, &mut temp);
std::mem::forget(temp);
}
})
}
fn main() {
let a = mut_to_pure(|a: &mut i32| *a = *a + 1)(5i32);
println!("{}", a);
let mut a = 7i32;
pure_to_mut(|a: i32| a + 1)(&mut a);
println!("{}", a);
}
@Sgeo
Copy link
Author

Sgeo commented Feb 7, 2015

Note that as noted in IRC by someone else, the unsafe code in pure_to_mut might not be safe in the event of a panic.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment