#closure #serialization #serde #distributed

nightly serde_closure

Serializable closures. This library provides macros to wrap closures such that they can serialized and sent between other processes running the same binary

6 releases

✓ Uses Rust 2018 edition

0.1.5 Jul 25, 2019
0.1.4 Jul 23, 2019
0.1.3 Aug 2, 2018
0.1.2 Jul 30, 2018

#107 in Encoding

Download history 13/week @ 2019-04-11 8/week @ 2019-04-18 14/week @ 2019-04-25 8/week @ 2019-05-02 14/week @ 2019-05-09 13/week @ 2019-05-16 17/week @ 2019-05-23 29/week @ 2019-05-30 11/week @ 2019-06-06 18/week @ 2019-06-13 17/week @ 2019-06-20 39/week @ 2019-06-27 27/week @ 2019-07-04 12/week @ 2019-07-11 59/week @ 2019-07-18

90 downloads per month
Used in 9 crates

MIT/Apache

59KB
940 lines

serde_closure

Crates.io MIT / Apache 2.0 licensed Build Status

Docs

Serializable closures.

This library provides macros to wrap closures such that they can 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 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::Code 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;
|a| num += a
let mut num = 0;
FnMut!([num] |a| *num += a)

Note: As this is a FnMut closure, num is a mutable reference, and must be dereferenced to use.

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!([hello, world] move |name| {
	*world += (hello.to_uppercase() + name).as_str();
})

Note: world must be dereferenced to use.

Cosmetic limitations

As visible above, there are currently some minor limitations:

  • The captured variables in FnMut and Fn closures are references, so need to be dereferenced;
  • Compiler errors are not as helpful as normal:
error[E0308]: mismatched types
...
   = note: expected type `for<..> fn(&'r mut (..), (..))`
              found type `[closure@<FnMut macros>:9:9: 10:44 my_var:_]`

means that my_var is a captured variable, but was not explicitly listed.

License

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.

Dependencies

~1.6–2.3MB
~51K SLoC