是否可以将包含闭包的 Rust 结构存储在不同的结构中?
Is it possible to store a Rust struct containing a closure in a different struct?
Crius 库提供
Rust 的类似断路器的功能。 Crius 定义了一个名为 Command
的结构,它看起来像这样:
pub struct Command<P, T, CMD>
where
T: Send,
CMD: Fn(P) -> Result<T, Box<CommandError>> + Sync + Send,
{
pub config: Option<Config>,
pub cmd: CMD,
phantom_data: PhantomData<P>,
}
是否可以将 Command
的实例存储为不同结构中的字段?
我开始尝试 return 从
功能。简单实例化类型没问题:
/// This function constructs a simple instance of `Command<P, T, CMD>` with the
/// types set to:
///
/// P ~ u8
/// T ~ u8
/// CMD: Fn(u8) -> Result<u8, Box<CommandError>> + Send + Sync
///
/// This function compiles fine. However, there is no *concrete* type
/// for `CMD`. In compiler output it will be referred to as an
/// "anonymous" type looking like this:
///
/// Command<u8, u8, [closure@src/lib.rs:19:21: 19:38]>
fn simple_command_instance() {
let _ = Command::define(|n: u8| Ok(n * 2));
}
为 return 类型编写时变得更加困难
功能:
fn return_command_instance() -> Command<u8, u8, ???> {
^
|
What goes here? -------
Command::define(|n: u8| Ok(n * 2))
}
编译器推断的类型是匿名的 - 不能放入
那里。很多时候,当关闭被传递时,人们求助于
使用 Box<F: Fn<...>>
,但是没有实现
impl Fn<T> for Box<Fn<T>>
- 所以装箱类型打破了
crius::command::Command
.
给出的约束
在具有新 impl Trait
功能的 Rust 版本中(例如
即将发布的稳定版本),这是可能的:
/// Use new `impl Trait` syntax as a type parameter in the return
/// type:
fn impl_trait_type_param() -> Command<u8, u8, impl Fn(u8) -> Result<u8, Box<CommandError>>> {
Command::define(|n: u8| Ok(n * 2))
}
这在稳定的 Rust 中不起作用,impl Trait
只能
用于 return 类型,而不是结构成员。
尝试传播通用类型最终看起来像
这个:
fn return_cmd_struct<F>() -> Command<u8, u8, F>
where
F: Fn(u8) -> Result<u8, Box<CommandError>> + Send + Sync,
{
Command::define(|n: u8| Ok(n * 2))
}
但这不能编译:
error[E0308]: mismatched types
--> src/lib.rs:33:21
|
33 | Command::define(|n: u8| Ok(n * 2))
| ^^^^^^^^^^^^^^^^^ expected type parameter, found closure
|
= note: expected type `F`
found type `[closure@src/lib.rs:33:21: 33:38]`
同样,我不知道在
结果签名。
即使将类型作为泛型参数传播有效,它也会
对于我们的特定用例来说仍然是一个问题。我们想存储一个
Command
作为注册为 actix 演员的一部分
SystemService
,这需要 Default
实现,这
再次最终迫使我们提供具体类型。
如果有人对此有任何想法,请分享
他们。当然知道不可能也很好。
我目前知道除了使用 impl
或 Box
之外,闭包不能用作 return 类型的一部分,您已经提到但不能在这种情况下使用。
另一种方法是使用函数指针而不是闭包,如下所示:
fn return_command_instance() -> Command<u8, u8, fn(u8) -> Result<u8, Box<CommandError>>> {
Command::define(|n: u8| Ok(n * 2))
}
注意小写 fn
表示函数指针而不是特征 Fn
。 Advanced Functions & Closures.
章节对此进行了更详细的解释
这仅在您不捕获函数中的任何变量时才有效,如果您这样做,它将被编译成一个闭包。
Crius 库提供
Rust 的类似断路器的功能。 Crius 定义了一个名为 Command
的结构,它看起来像这样:
pub struct Command<P, T, CMD>
where
T: Send,
CMD: Fn(P) -> Result<T, Box<CommandError>> + Sync + Send,
{
pub config: Option<Config>,
pub cmd: CMD,
phantom_data: PhantomData<P>,
}
是否可以将 Command
的实例存储为不同结构中的字段?
我开始尝试 return 从 功能。简单实例化类型没问题:
/// This function constructs a simple instance of `Command<P, T, CMD>` with the
/// types set to:
///
/// P ~ u8
/// T ~ u8
/// CMD: Fn(u8) -> Result<u8, Box<CommandError>> + Send + Sync
///
/// This function compiles fine. However, there is no *concrete* type
/// for `CMD`. In compiler output it will be referred to as an
/// "anonymous" type looking like this:
///
/// Command<u8, u8, [closure@src/lib.rs:19:21: 19:38]>
fn simple_command_instance() {
let _ = Command::define(|n: u8| Ok(n * 2));
}
为 return 类型编写时变得更加困难 功能:
fn return_command_instance() -> Command<u8, u8, ???> {
^
|
What goes here? -------
Command::define(|n: u8| Ok(n * 2))
}
编译器推断的类型是匿名的 - 不能放入
那里。很多时候,当关闭被传递时,人们求助于
使用 Box<F: Fn<...>>
,但是没有实现
impl Fn<T> for Box<Fn<T>>
- 所以装箱类型打破了
crius::command::Command
.
在具有新 impl Trait
功能的 Rust 版本中(例如
即将发布的稳定版本),这是可能的:
/// Use new `impl Trait` syntax as a type parameter in the return
/// type:
fn impl_trait_type_param() -> Command<u8, u8, impl Fn(u8) -> Result<u8, Box<CommandError>>> {
Command::define(|n: u8| Ok(n * 2))
}
这在稳定的 Rust 中不起作用,impl Trait
只能
用于 return 类型,而不是结构成员。
尝试传播通用类型最终看起来像 这个:
fn return_cmd_struct<F>() -> Command<u8, u8, F>
where
F: Fn(u8) -> Result<u8, Box<CommandError>> + Send + Sync,
{
Command::define(|n: u8| Ok(n * 2))
}
但这不能编译:
error[E0308]: mismatched types
--> src/lib.rs:33:21
|
33 | Command::define(|n: u8| Ok(n * 2))
| ^^^^^^^^^^^^^^^^^ expected type parameter, found closure
|
= note: expected type `F`
found type `[closure@src/lib.rs:33:21: 33:38]`
同样,我不知道在 结果签名。
即使将类型作为泛型参数传播有效,它也会
对于我们的特定用例来说仍然是一个问题。我们想存储一个
Command
作为注册为 actix 演员的一部分
SystemService
,这需要 Default
实现,这
再次最终迫使我们提供具体类型。
如果有人对此有任何想法,请分享 他们。当然知道不可能也很好。
我目前知道除了使用 impl
或 Box
之外,闭包不能用作 return 类型的一部分,您已经提到但不能在这种情况下使用。
另一种方法是使用函数指针而不是闭包,如下所示:
fn return_command_instance() -> Command<u8, u8, fn(u8) -> Result<u8, Box<CommandError>>> {
Command::define(|n: u8| Ok(n * 2))
}
注意小写 fn
表示函数指针而不是特征 Fn
。 Advanced Functions & Closures.
这仅在您不捕获函数中的任何变量时才有效,如果您这样做,它将被编译成一个闭包。