匿名函数 - 由于需求冲突,无法推断出合适的生命周期
Anonymous function - cannot infer an appropriate lifetime due to conflicting requirements
我正在尝试使用策略模式来使用不同的方法从输入列表生成操作。
use rand::{prelude::SliceRandom, Rng};
#[derive(Debug, Clone)]
struct Inner {
num: usize,
}
#[derive(Debug)]
enum Outer {
ActionA(Inner),
ActionB(Inner),
}
fn main() {
// A method to generate an Outer from a list of Inners
type Strategy = Box<dyn Fn(&Vec<&Inner>) -> Box<dyn FnMut() -> Outer>>;
let random_strategy: Strategy = Box::new(|inners| {
let mut rng = rand::thread_rng();
Box::new(move || {
let inner = inners.choose(&mut rng).unwrap();
if rng.gen_bool(1.0 / 2.0) {
Outer::ActionA(inner.to_owned().clone())
} else {
Outer::ActionB(inner.to_owned().clone())
}
})
});
let inners = vec![&Inner { num: 3 }, &Inner { num: 4 }];
let get_choice = random_strategy(&inners);
for _ in 0..4 {
let choice = get_choice();
println!("{:?}", choice);
// do something...
}
}
每个策略都是一个闭包,因为它可能包含一些状态(为了简化示例,此处未显示)。
我收到编译器错误
cannot infer an appropriate lifetime due to conflicting requirements
expected `(&&Vec<&Inner>, &mut ThreadRng)`
found `(&&Vec<&Inner>, &mut ThreadRng)`
but, the lifetime must be valid for the static lifetime...
expected `Box<(dyn FnMut() -> Outer + 'static)>`
found `Box<dyn FnMut() -> Outer>`
我很困惑为什么输出 Outer
必须具有静态生命周期。我正在创建 Outer
一次,使用完全拥有的 Inner
(克隆后),从匿名函数返回它,并且再也不会在该匿名函数中使用它。我希望调用者 (let choice = get_choice()
) 拥有 Outer
.
的所有权
This 问题有相同的错误但有所不同,因为在我的示例中,Outer
需要拥有 Inner
.
我可以将策略定义更改为
type Strategy<'a> = Box<dyn Fn(&'a Vec<&'a Inner>) -> Box<dyn FnMut() -> Outer>>;
但是我得到了错误
`inners` does not live long enough
borrowed value does not live long enoughrustcE0597
main.rs(38, 1): `inners` dropped here while still borrowed
main.rs(18, 26): type annotation requires that `inners` is borrowed for `'static`
(第38行是main函数的结尾)
每次我想使用策略时,我不确定如何在不克隆整个内部结构的情况下解决这个问题。
问题在于
move || {
let inner = inners.choose(&mut rng).unwrap();
if rng.gen_bool(1.0 / 2.0) {
Outer::ActionA(inner.to_owned().clone())
} else {
Outer::ActionB(inner.to_owned().clone())
}
}
捕获inners
,也就是你传入外层闭包的&Vec<&Inner>
。 inners
不受 'static
的限制,因此闭包作为一个整体不能强制转换为 dyn FnMut() -> Outer
,即 隐式 dyn (FnMut() -> Outer) + 'static
。
要解决此问题,您可以允许策略 return 不是 'static
的函数,方法是像这样重新定义类型:
type Strategy = Box<
dyn for<'a>
Fn(&'a Vec<&'a Inner>) -> Box<dyn (FnMut() -> Outer) + 'a>
>;
注意 for<'a>
。这是 trait-bound 语法,等同于声明一个像
这样的函数
fn example_strategy<'a>(&'a Vec<&'a Inner>) -> Box<dyn (FnMut() -> Outer) + 'a> {...}
函数输出的生命周期取决于输入。
进行此更改并添加缺少的 mut
限定符(调用 FnMut
需要对该函数进行可变访问),您的程序将编译。
也许您希望 FnMut() -> Outer
保留 'static
;在这种情况下,您需要定义 Strategy
以便它 拥有 Inner
,并相应更改您对它的称呼。但是您可能不想要这个,因为您提到不克隆 Inner
;我提到它是为了比较。
type Strategy = Box<dyn Fn(Vec<Inner>) -> Box<dyn FnMut() -> Outer>>;
我正在尝试使用策略模式来使用不同的方法从输入列表生成操作。
use rand::{prelude::SliceRandom, Rng};
#[derive(Debug, Clone)]
struct Inner {
num: usize,
}
#[derive(Debug)]
enum Outer {
ActionA(Inner),
ActionB(Inner),
}
fn main() {
// A method to generate an Outer from a list of Inners
type Strategy = Box<dyn Fn(&Vec<&Inner>) -> Box<dyn FnMut() -> Outer>>;
let random_strategy: Strategy = Box::new(|inners| {
let mut rng = rand::thread_rng();
Box::new(move || {
let inner = inners.choose(&mut rng).unwrap();
if rng.gen_bool(1.0 / 2.0) {
Outer::ActionA(inner.to_owned().clone())
} else {
Outer::ActionB(inner.to_owned().clone())
}
})
});
let inners = vec![&Inner { num: 3 }, &Inner { num: 4 }];
let get_choice = random_strategy(&inners);
for _ in 0..4 {
let choice = get_choice();
println!("{:?}", choice);
// do something...
}
}
每个策略都是一个闭包,因为它可能包含一些状态(为了简化示例,此处未显示)。
我收到编译器错误
cannot infer an appropriate lifetime due to conflicting requirements
expected `(&&Vec<&Inner>, &mut ThreadRng)`
found `(&&Vec<&Inner>, &mut ThreadRng)`
but, the lifetime must be valid for the static lifetime...
expected `Box<(dyn FnMut() -> Outer + 'static)>`
found `Box<dyn FnMut() -> Outer>`
我很困惑为什么输出 Outer
必须具有静态生命周期。我正在创建 Outer
一次,使用完全拥有的 Inner
(克隆后),从匿名函数返回它,并且再也不会在该匿名函数中使用它。我希望调用者 (let choice = get_choice()
) 拥有 Outer
.
This 问题有相同的错误但有所不同,因为在我的示例中,Outer
需要拥有 Inner
.
我可以将策略定义更改为
type Strategy<'a> = Box<dyn Fn(&'a Vec<&'a Inner>) -> Box<dyn FnMut() -> Outer>>;
但是我得到了错误
`inners` does not live long enough
borrowed value does not live long enoughrustcE0597
main.rs(38, 1): `inners` dropped here while still borrowed
main.rs(18, 26): type annotation requires that `inners` is borrowed for `'static`
(第38行是main函数的结尾)
每次我想使用策略时,我不确定如何在不克隆整个内部结构的情况下解决这个问题。
问题在于
move || {
let inner = inners.choose(&mut rng).unwrap();
if rng.gen_bool(1.0 / 2.0) {
Outer::ActionA(inner.to_owned().clone())
} else {
Outer::ActionB(inner.to_owned().clone())
}
}
捕获inners
,也就是你传入外层闭包的&Vec<&Inner>
。 inners
不受 'static
的限制,因此闭包作为一个整体不能强制转换为 dyn FnMut() -> Outer
,即 隐式 dyn (FnMut() -> Outer) + 'static
。
要解决此问题,您可以允许策略 return 不是 'static
的函数,方法是像这样重新定义类型:
type Strategy = Box<
dyn for<'a>
Fn(&'a Vec<&'a Inner>) -> Box<dyn (FnMut() -> Outer) + 'a>
>;
注意 for<'a>
。这是 trait-bound 语法,等同于声明一个像
fn example_strategy<'a>(&'a Vec<&'a Inner>) -> Box<dyn (FnMut() -> Outer) + 'a> {...}
函数输出的生命周期取决于输入。
进行此更改并添加缺少的 mut
限定符(调用 FnMut
需要对该函数进行可变访问),您的程序将编译。
也许您希望 FnMut() -> Outer
保留 'static
;在这种情况下,您需要定义 Strategy
以便它 拥有 Inner
,并相应更改您对它的称呼。但是您可能不想要这个,因为您提到不克隆 Inner
;我提到它是为了比较。
type Strategy = Box<dyn Fn(Vec<Inner>) -> Box<dyn FnMut() -> Outer>>;