25次发布
0.3.3 | 2022年11月24日 |
---|---|
0.3.2 | 2020年8月5日 |
0.3.1 | 2020年7月14日 |
0.2.10 | 2020年2月5日 |
0.1.2 | 2018年7月30日 |
在编码类别中排名第316
每月下载量370次
在19个crate中(14个直接使用)
39KB
692 行
serde_closure
可序列化和可调试的闭包。
该库提供了宏,可以将闭包包装起来使其可序列化和可调试。
use serde_closure::{traits::Fn, Fn};
let one = 1;
let plus_one = Fn!(|x: i32| x + one);
assert_eq!(2, plus_one.call((1,))); // this works on stable and nightly
// assert_eq!(2, plus_one(1)); // this only works on nightly
println!("{:#?}", plus_one);
// prints:
// Fn<main::{{closure}} at main.rs:6:15> {
// one: 1,
// source: "| x : i32 | x + one",
// }
该库旨在尽可能简单和安全地工作。在稳定版Rust中,包装的闭包实现了 traits::FnOnce
、traits::FnMut
和 traits::Fn
,在夜间版Rust中,使用 unboxed_closures
和 fn_traits
功能(rust issue #29625)实现了 std::ops::FnOnce
、std::ops::FnMut
和 std::ops::Fn
。
- 有三个宏,分别是
FnOnce
、FnMut
和Fn
,分别对应Rust的三个闭包类型。 - 将你的闭包用宏之一包装起来,它现在将实现
Copy
、Clone
、PartialEq
、Eq
、Hash
、PartialOrd
、Ord
、Serialize
、Deserialize
和Debug
。 - 以下列出了一些细微的语法限制。
- 此包有一个不可避免但已记录且合理的
unsafe
使用。
包装闭包的示例
推断的、非捕获闭包
|a| a+1
FnMut!(|a| a+1)
注解的、非捕获闭包
|a: String| -> String { a.to_uppercase() }
FnMut!(|a: String| -> String { a.to_uppercase() })
推断的闭包,捕获 num
let mut num = 0;
|a| num += a
let mut num = 0;
FnMut!(|a| num += a)
move
闭包,捕获 hello
和 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();
})
限制
目前存在一些细微的限制
- 以小写字母开头的类型可能需要与变量区分。如果您看到如下错误,请修正类型的大小写,或者通过添加
my_struct::<>
来消除歧义。
error[E0308]: mismatched types
--> tests/test.rs:450:4
|
449 | FnOnce!(move || {
| _____-
450 | | my_struct;
| | ^^^^^^^^^ expected struct `serde_closure::internal::a_variable`, found struct `my_struct`
451 | | });
| |______- in this macro invocation
|
= note: expected type `serde_closure::internal::a_variable`
found type `my_struct`
- 以大写字母开头的变量可能需要与类型区分。如果您看到如下错误,请修正变量的大小写,或者用
(MyVariable)
包装它以消除歧义。
error: imports cannot refer to local variables
--> tests/test.rs:422:3
|
417 | FnOnce!(move || {
| _____-
418 | | MyVariable;
| | ^^^^^^^^^^
419 | | });
| |______- in this macro invocation
|
- 闭包内调用的函数和闭包可能需要消除歧义。这可以通过与上述相同的方式完成,使用
function::<>
为函数和(closure)
为闭包。
进程间的序列化
此包创建的闭包是不可命名的 - 即,与普通闭包一样,没有 Rust 语法可以用来编写类型。这意味着要反序列化闭包,您要么需要指定正在反序列化的确切类型而不命名它(这是可能的但不太实用),或者通过将类型存储在一个 trait object 中来 擦除 类型。
serde_traitobject
包允许 trait objects 在运行相同二进制文件的其他进程之间安全地序列化和传递。
例如,如果您有多个进程的副本,或者在每个集群机器上运行的相同二进制文件,serde_traitobject
将帮助您在它们之间发送可序列化的闭包。这可以通过将闭包向上转换为 Box<dyn serde_traitobject::Fn()>
来实现,它是自动可序列化和反序列化的,与 serde
一起。
许可证
根据以下任一项获得许可
- Apache License,版本 2.0,(LICENSE-APACHE.txt 或 http://www.apache.org/licenses/LICENSE-2.0)
- 麻省理工学院许可证(《LICENSE-MIT.txt》或http://opensource.org/licenses/MIT)
根据您的选择。
除非您明确表示否则,您根据Apache-2.0许可证定义的任何有意提交以包含在工作中的贡献,将如上双许可,不附加任何额外条款或条件。
依赖项
~0.4–1MB
~22K SLoC