[英]Anonymous function - cannot infer an appropriate lifetime due to conflicting requirements
I am trying to use the strategy pattern to have different methods for generating actions from a list of input.我正在尝试使用策略模式来使用不同的方法从输入列表中生成操作。
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...
}
}
Each strategy is a closure because it may contain some state (not shown here in order to keep the example simple).每个策略都是一个闭包,因为它可能包含一些状态(为了保持示例简单,此处未显示)。
I get the compiler error我收到编译器错误
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>`
I'm confused as to why the output Outer
must have a static lifetime.我很困惑为什么输出
Outer
必须具有静态生命周期。 I am creating Outer
once, using a wholly-owned Inner
(after cloning), returning it from the anonymous function, and never using it again in that anonymous function.我正在创建
Outer
一次,使用全资拥有的Inner
(克隆后),从匿名函数返回它,并且不再在该匿名函数中使用它。 I would expect that the caller ( let choice = get_choice()
) would have ownership over Outer
.我希望调用者(
let choice = get_choice()
)拥有对Outer
所有权。
This question has the same error but differs because, in my example, Outer
needs to own Inner
. 这个问题有相同的错误,但有所不同,因为在我的例子中,
Outer
需要拥有Inner
。
I can change the strategy definition to我可以将策略定义更改为
type Strategy<'a> = Box<dyn Fn(&'a Vec<&'a Inner>) -> Box<dyn FnMut() -> Outer>>;
but then I get the error但后来我得到了错误
`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`
(Line 38 is the end of the main function) (第38行是main函数的结尾)
I'm unsure how to fix this without cloning the entirety of inners each time I want to use a strategy.每次我想使用策略时,我不确定如何在不克隆整个内部的情况下解决这个问题。
The problem is that问题是
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())
}
}
captures inners
, which is the &Vec<&Inner>
you passed in to the outer closure.捕获
inners
,这是您传递给外部闭包的&Vec<&Inner>
。 inners
is not bounded by 'static
, so the closure as a whole cannot be coerced to dyn FnMut() -> Outer
, which is implicitly dyn (FnMut() -> Outer) + 'static
. inners
不受'static
,因此整个闭包不能被强制为dyn FnMut() -> Outer
,这隐式是dyn (FnMut() -> Outer) + 'static
。
To fix this, you can allow the Strategy to return a function that isn't 'static
, by redefining the type like so:要解决此问题,您可以通过重新定义类型来允许 Strategy 返回一个不是
'static
的函数,如下所示:
type Strategy = Box<
dyn for<'a>
Fn(&'a Vec<&'a Inner>) -> Box<dyn (FnMut() -> Outer) + 'a>
>;
Note the for<'a>
.注意
for<'a>
。 This is the trait-bound syntax equivalent to declaring a function like这是等价于声明一个函数的 trait-bound 语法
fn example_strategy<'a>(&'a Vec<&'a Inner>) -> Box<dyn (FnMut() -> Outer) + 'a> {...}
where the function output has a lifetime depending on the input.其中函数输出的生命周期取决于输入。
With this change, and adding a missing mut
qualifier (calling a FnMut
requires mutable access to the function), your program will compile.通过此更改,并添加缺少的
mut
限定符(调用FnMut
需要对该函数进行可变访问),您的程序将编译。
Maybe you want the FnMut() -> Outer
to stay 'static
;也许您希望
FnMut() -> Outer
保持'static
; in that case, you'd need to define Strategy
so that it owns the Inner
s, with corresponding changes to how you call it.在这种情况下,您需要定义
Strategy
以便它拥有Inner
s,并相应地更改您的调用方式。 But you probably don't want this since you mentioned not cloning the Inner
s;但是你可能不想要这个,因为你提到不要克隆
Inner
; I'm mentioning it for comparison.我提到它是为了比较。
type Strategy = Box<dyn Fn(Vec<Inner>) -> Box<dyn FnMut() -> Outer>>;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.