[−][src]Crate serde_closure
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 multiple forks of a process, or 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, safe 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
andFn
, corresponding to the three types of Rust closure. - Wrap your closure with one of the macros and it will now implement
Copy
,Clone
,PartialEq
,Eq
,Hash
,PartialOrd
,Ord
,Serialize
,Deserialize
andDebug
. - There are some minor syntax limitations, which are documented below.
- This crate has one unavoidable but documented and sound usage of
unsafe
.
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; |a| num += a
let mut num = 0; FnMut!(|a| num += a)
move
closure, capturing hello
and world
:
let hello = String::from("hello"); let mut world = String::new(); move |name| { world += (hello.to_uppercase() + name).as_str(); }
let hello = String::from("hello"); let mut world = String::new(); FnMut!(move |name| { world += (hello.to_uppercase() + name).as_str(); })
Limitations
There are currently some minor limitations:
- Captured variables with an uppercase first letter need to be explicitly captured. If you see a panic like the following, fix the case of the variable.
thread 'main' panicked at 'A variable with an upper case first letter was implicitly captured.
Unfortunately due to current limitations it must be captured explicitly.
Please refer to the README.', tests/test.rs:205:10
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace.
- Functions called inside the closure might need to be disambiguated. This
also affects enum unit and tuple variants with a lowercase first letter.
If you see an error like either of the following, qualify
my_function
asself::my_function
andmy_enum_variant
asMyEnum::my_enum_variant
.
error[E0277]: the trait bound `fn(usize) -> std::option::Option<usize> {my_function::<usize>}: fnref::_IMPL_DESERIALIZE_FOR_Fn::_serde::Serialize` is not satisfied
--> tests/test.rs:327:10
|
314 | fn unfold<A, St, F>(initial_state: St, f: F) -> Unfold<St, F>
| ------
315 | where
316 | F: Fn(&mut St) -> Option<A> + Serialize,
| --------- required by this bound in `fnref::unfold`
...
327 | let _ = unfold(0_usize, Fn!(|acc: &mut _| my_function(*acc)));
| ^^^^^^ the trait `fnref::_IMPL_DESERIALIZE_FOR_Fn::_serde::Serialize` is not implemented for `fn(usize) -> std::option::Option<usize> {my_function::<usize>}`
error[E0530]: function parameters cannot shadow tuple variants
--> tests/test.rs:173:47
|
173 | FnMut!(|acc: &mut _| my_enum_variant(*acc))
| ---------------------^^^^^^^^^^^^^^^-------
| | |
| | cannot be named the same as a tuple variant
| in this macro invocation
Macros
Fn | Macro that wraps a closure, evaluating to a |
FnMut | Macro that wraps a closure, evaluating to a |
FnOnce | Macro that wraps a closure, evaluating to a |
Structs
Fn | A struct representing a serializable closure, created by the |
FnMut | A struct representing a serializable closure, created by the
|
FnOnce | A struct representing a serializable closure, created by the
|