Rust - 闭包和泛型
Rust - clousures and generic types
老实说,我很难用语言描述这个问题,所以我马上展示代码:
// SomeType / SomeTrait
struct SomeType;
trait SomeTrait {
fn do_sth() -> &'static str;
}
impl SomeTrait for SomeType {
fn do_sth() -> &'static str {
"do_sth()"
}
}
// SomeOtherType / SomeOtherTrait
struct SomeOtherType;
impl SomeOtherType {
fn get_some_trait<C>(&self, c: C)
where
C: Fn(SomeType), // Takes clousure, clousure have to get `SomeType`-type paramm
{
c(SomeType);
}
}
trait SomeOtherTrait {
fn perform_sth<C, D>(&self, c: C)
where
D: SomeTrait,
C: Fn(&D) -> &'static str; // Takes clousure, clousure have to get type that implements SomeTrait
}
impl SomeOtherTrait for SomeOtherType {
fn perform_sth<C, D>(&self, c: C)
where
D: SomeTrait,
C: Fn(&D) -> &'static str,
{
self.get_some_trait(|arg: SomeType| {
c(&arg); // <- Problem
// Error: expected type parameter `D`, found struct `SomeType`
// But `D: SomeTrait` and SomeType implements `SomeTrait`
});
}
}
fn main() {}
上面的代码是我所处情况的简化模型。
如果我有 |arg: SomeType|
,c
clousure 引用通用类型 T
,实现 SomeType
- 为什么我不能传递 arg
作为 c
?
的参数
预先感谢您帮助解决问题。对于我英语中的任何错误,我深表歉意。
我认为您当前对 SomeOtherTrait
的定义不允许这样做,因为它通过在 perform_sth
上定义它来将 D
参数填充给调用者,但您在内部已经绑定它是 SomeType
凭借 SomeOtherType::get_some_trait
.
如果在 SomeOtherTrait
上引入通用参数 D
,则可以将 SomeOtherTrait
的给定类型实现中的 D
绑定到它需要的任何内容:
trait SomeOtherTrait<D> {
fn perform_sth<C>(&self, c: C)
where
D: SomeTrait,
C: Fn(&D) -> &'static str; // Takes clousure, clousure have to get type that implements SomeTrait
}
impl SomeOtherTrait<SomeType> for SomeOtherType {
fn perform_sth<C>(&self, c: C)
where
C: Fn(&SomeType) -> &'static str,
{
self.get_some_trait(|arg| {
c(&arg);
});
}
}
另一个选项是将 get_some_trait
调整为对 c
的参数通用,尽管您随后需要能够构造它,例如通过 D::Default()
:
// ...
struct SomeOtherType;
impl SomeOtherType {
fn get_some_trait<C, D>(&self, c: C)
where
D: Default,
C: Fn(D), // Takes clousure, clousure have to get `SomeType`-type paramm
{
c(D::default());
}
}
// ...
这又需要将 D: Default
绑定到 SomeOtherTrait::perform_sth
。
问题是这仅在 D
为 SomeType
时有效。比如说我有下面的代码:
struct Foo;
impl SomeTrait for Foo {
fn do_sth() -> &'static str {
"Foo"
}
}
SomeOtherType.perform_sth::<_, Foo>(|_: &Foo| "Bla" );
此代码完全有效,但 perform_sth
的当前实现尝试使用 SomeType
,尽管我的闭包预期应使用 Foo
。
老实说,我很难用语言描述这个问题,所以我马上展示代码:
// SomeType / SomeTrait
struct SomeType;
trait SomeTrait {
fn do_sth() -> &'static str;
}
impl SomeTrait for SomeType {
fn do_sth() -> &'static str {
"do_sth()"
}
}
// SomeOtherType / SomeOtherTrait
struct SomeOtherType;
impl SomeOtherType {
fn get_some_trait<C>(&self, c: C)
where
C: Fn(SomeType), // Takes clousure, clousure have to get `SomeType`-type paramm
{
c(SomeType);
}
}
trait SomeOtherTrait {
fn perform_sth<C, D>(&self, c: C)
where
D: SomeTrait,
C: Fn(&D) -> &'static str; // Takes clousure, clousure have to get type that implements SomeTrait
}
impl SomeOtherTrait for SomeOtherType {
fn perform_sth<C, D>(&self, c: C)
where
D: SomeTrait,
C: Fn(&D) -> &'static str,
{
self.get_some_trait(|arg: SomeType| {
c(&arg); // <- Problem
// Error: expected type parameter `D`, found struct `SomeType`
// But `D: SomeTrait` and SomeType implements `SomeTrait`
});
}
}
fn main() {}
上面的代码是我所处情况的简化模型。
如果我有 |arg: SomeType|
,c
clousure 引用通用类型 T
,实现 SomeType
- 为什么我不能传递 arg
作为 c
?
预先感谢您帮助解决问题。对于我英语中的任何错误,我深表歉意。
我认为您当前对 SomeOtherTrait
的定义不允许这样做,因为它通过在 perform_sth
上定义它来将 D
参数填充给调用者,但您在内部已经绑定它是 SomeType
凭借 SomeOtherType::get_some_trait
.
如果在 SomeOtherTrait
上引入通用参数 D
,则可以将 SomeOtherTrait
的给定类型实现中的 D
绑定到它需要的任何内容:
trait SomeOtherTrait<D> {
fn perform_sth<C>(&self, c: C)
where
D: SomeTrait,
C: Fn(&D) -> &'static str; // Takes clousure, clousure have to get type that implements SomeTrait
}
impl SomeOtherTrait<SomeType> for SomeOtherType {
fn perform_sth<C>(&self, c: C)
where
C: Fn(&SomeType) -> &'static str,
{
self.get_some_trait(|arg| {
c(&arg);
});
}
}
另一个选项是将 get_some_trait
调整为对 c
的参数通用,尽管您随后需要能够构造它,例如通过 D::Default()
:
// ...
struct SomeOtherType;
impl SomeOtherType {
fn get_some_trait<C, D>(&self, c: C)
where
D: Default,
C: Fn(D), // Takes clousure, clousure have to get `SomeType`-type paramm
{
c(D::default());
}
}
// ...
这又需要将 D: Default
绑定到 SomeOtherTrait::perform_sth
。
问题是这仅在 D
为 SomeType
时有效。比如说我有下面的代码:
struct Foo;
impl SomeTrait for Foo {
fn do_sth() -> &'static str {
"Foo"
}
}
SomeOtherType.perform_sth::<_, Foo>(|_: &Foo| "Bla" );
此代码完全有效,但 perform_sth
的当前实现尝试使用 SomeType
,尽管我的闭包预期应使用 Foo
。