Crate serde_closure[−][src]
Serializable closures.
This library provides macros to wrap closures such that they can be serialized and sent between other processes running the same binary.
fn sum_of_squares(input: &[i32]) -> i32 { input.dist_iter() .map(Fn!(|&i| i * i)) .sum() }
For example, if you have the same binary running on each of a cluster of machines, this library would help you to send closures between them.
This library aims to work in as simple and un-magical a way as possible. It
currently requires nightly Rust for the unboxed_closures
and fn_traits
features (rust issue
#29625).
- There are three macros, FnOnce, FnMut and Fn, corresponding to the three types of Rust closure.
- The captured variables, i.e. those variables that are referenced by the closure but are declared outside of it, must be explicitly listed.
- There are currently some minor limitations of syntax over normal closure syntax, which are documented below.
- The closure is coerced to a function pointer, which is wrapped by relative::Pointer such that it can safely be sent between processes.
Examples of wrapped closures
Inferred, non-capturing closure:
|a| a+1
FnMut!(|a| a+1)
Annotated, non-capturing closure:
|a: String| -> String { a.to_uppercase() }
FnMut!(|a: String| -> String { a.to_uppercase() })
Inferred closure, capturing num
:
let mut num = 0; move |a| num += a
let mut num = 0; FnMut!([num] move |a| *num += a)
Note: If any variables are captured then the move
keyword must be present.
As this is a FnMut closure, num
is a mutable reference, and must be
dereferenced to use.
Capturing hello
requiring extra annotation:
let mut hello = String::new(); move |a| { hello = hello.to_uppercase() + a; hello.clone() }
let mut hello = String::new(); FnMut!([hello] move |a| { let hello: &mut String = hello; *hello = hello.to_uppercase() + a; hello.clone() })
Note: hello
needs its type annotated in the closure.
Complex closure, capturing a
and b
:
let (mut a, mut b) = (1usize, String::from("foo")); move |c, d: &_, e: &mut _, f: String, g: &String, h: &mut String| { *e += a + c + *d; a += *e; *h += (b.clone() + f.as_str() + g.as_str()).as_str(); b += h.as_str(); }
let (mut a, mut b) = (1usize, String::from("foo")); FnMut!([a,b] move |c:_, d: &_, e: &mut _, f: String, g: &String, h: &mut String| { let b: &mut String = b; *e += *a + c + *d; *a += *e; *h += ((b.clone() + f.as_str() + g.as_str())).as_str(); *b += h.as_str(); })
Cosmetic limitations
As visible above, there are currently some limitations that often necessitate extra annotation that you might typically expect to be redundant.
- Type inference doesn't work as well as normal, hence extra type annotations might be needed;
- The captured variables in FnMut and Fn closures are references, so need to be dereferenced;
- Types cannot be annotated in the list of captured variables;
- If any of the closure arguments are annotated with types (i.e.
|a:i32|0
) then all must be (though_
can be used), and patterns can no longer be used (i.e.|&a:&i32|0
will not work). - The
move
keyword must be present if any variables are captured.
Macros
Fn |
Macro that wraps a closure, evaluating to a Fn struct that implements std::ops::Fn, serde's Serialize and Deserialize, and various convenience traits. |
FnMut |
Macro that wraps a closure, evaluating to a FnMut struct that implements std::ops::FnMut, serde's Serialize and Deserialize, and various convenience traits. |
FnOnce |
Macro that wraps a closure, evaluating to a FnOnce struct that implements std::ops::FnOnce, serde's Serialize and Deserialize, and various convenience traits. |
Structs
Fn |
A struct representing a serializable closure, created by the Fn macro. Implements std::ops::Fn, serde's Serialize and Deserialize, and various convenience traits. |
FnMut |
A struct representing a serializable closure, created by the FnMut macro. Implements std::ops::FnMut, serde's Serialize and Deserialize, and various convenience traits. |
FnOnce |
A struct representing a serializable closure, created by the FnOnce macro. Implements std::ops::FnOnce, serde's Serialize and Deserialize, and various convenience traits. |