Serializable closures.
This library provides macros to wrap closures such that they can serialized and sent between other processes running the same binary.
rust
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).
FnOnce
,
FnMut
and Fn
,
corresponding to the three types of Rust closure.Copy
,
Clone
, PartialEq
, Eq
, Hash
, PartialOrd
, Ord
, Serialize
,
Deserialize
and Debug
.unsafe
.Inferred, non-capturing closure:
rust
|a| a+1
rust
FnMut!(|a| a+1)
Annotated, non-capturing closure:
rust
|a: String| -> String { a.to_uppercase() }
rust
FnMut!(|a: String| -> String { a.to_uppercase() })
Inferred closure, capturing num
:
rust
let mut num = 0;
|a| num += a
rust
let mut num = 0;
FnMut!(|a| num += a)
move
closure, capturing hello
and world
:
rust
let hello = String::from("hello");
let mut world = String::new();
move |name| {
world += (hello.to_uppercase() + name).as_str();
}
rust
let hello = String::from("hello");
let mut world = String::new();
FnMut!(move |name| {
world += (hello.to_uppercase() + name).as_str();
})
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.
text
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
as self::my_function
and my_enum_variant
as
MyEnum::my_enum_variant
.
text
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>}`
text
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
Licensed under either of
at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.