[英]How to return a struct with a reference to self in Rust?
I've implemented a struct
which has a list of crontab entries, each of which knows its own recurrence (such as */5 * * * *
in crontab): 我已经实现了一个
struct
,其中包含一个crontab条目列表,每个条目都知道它自己的重复发生(例如crontab中的*/5 * * * *
):
extern crate chrono;
use chrono::NaiveDateTime;
pub struct Crontab<'a> {
entries: Vec<Entry<'a>>,
}
pub struct Entry<'a> {
pub recurrence: Recurrence,
pub command: &'a str,
}
pub struct Recurrence {
minutes: Vec<u8>,
hours: Vec<u8>,
days_of_month: Vec<u8>,
months: Vec<u8>,
days_of_week: Vec<u8>,
}
Based on the current time you can get the next occurrence of a command: 根据当前时间,您可以获得下一个命令:
impl Recurrence {
pub fn next_match(&self, after: NaiveDateTime) -> NaiveDateTime {
unimplemented!()
}
}
I'm trying to write a function on Crontab
to get the Entry
which will run next (that is, for which recurrence.next_match()
is the lowest). 我正在尝试在
Crontab
上编写一个函数来获取下一个将运行的Entry
(也就是说, recurrence.next_match()
是最低的)。
impl<'a> Crontab<'a> {
fn next_run(&self, from: NaiveDateTime) -> Run<'a> {
&self.entries
.into_iter()
.map(|entry| Run {
entry: &entry,
datetime: entry.recurrence.next_match(from),
})
.min_by(|this, other| this.datetime.cmp(&other.datetime))
.unwrap()
}
}
struct Run<'a> {
entry: &'a Entry<'a>,
datetime: NaiveDateTime,
}
This generates the error: 这会生成错误:
error[E0308]: mismatched types
--> src/main.rs:30:9
|
29 | fn next_run(&self, from: NaiveDateTime) -> Run<'a> {
| ------- expected `Run<'a>` because of return type
30 | / &self.entries
31 | | .into_iter()
32 | | .map(|entry| Run {
33 | | entry: &entry,
... |
36 | | .min_by(|this, other| this.datetime.cmp(&other.datetime))
37 | | .unwrap()
| |_____________________^ expected struct `Run`, found &Run<'_>
|
= note: expected type `Run<'a>`
found type `&Run<'_>`
Similar variants I've tried fail to compile with messages such as "cannot move out of borrowed content" (if changing the return type to &Run<'a>
) or that the &entry
does not live long enough. 我尝试过的类似变体无法使用诸如“无法移出借来的内容”之类的消息进行编译(如果将返回类型更改为
&Run<'a>
)或者&entry
生存时间不够长。
It seems to make most sense that the Run
should have a reference to rather than a copy of the Entry
, but I'm not sure how to juggle both the lifetimes and references to get to that point (and I don't know whether 'a
refers to the same lifetime in both structs). 似乎最有意义的是
Run
应该引用而不是Entry
的副本,但我不确定如何兼顾生命周期和引用以达到这一点(我不知道是否'a
指的是两种结构中相同的寿命)。 What am I missing here? 我在这里错过了什么?
As described in Is there any way to return a reference to a variable created in a function? 如有没有办法返回对函数中创建的变量的引用? , you cannot create a value in a function and return a reference to it.
,您无法在函数中创建值并返回对它的引用。 Nothing would own the result of your iterator chain, thus the reference would point at invalid data.
没有什么会拥有迭代器链的结果,因此引用将指向无效数据。
That doesn't even really matter: as pointed out in the comments, you cannot call into_iter
on self.entries
because you cannot move out of borrowed content to start with, as described in Cannot move out of borrowed content . 甚至不真正的问题:如在评论中指出,你不能叫
into_iter
上self.entries
,因为你不能搬出借来的内容入手,如在不能迁出借来的内容 。 This means that we cannot have an owned value of an Entry
as the result of the iterator chain to start with. 这意味着我们不能拥有一个
Entry
的拥有值作为迭代器链的结果。
Crontab
owns the Entry
; Crontab
拥有Entry
; as soon as the Crontab
moves, any reference to any Entry
becomes invalid. 一旦
Crontab
移动,对任何Entry
任何引用都将变为无效。 This means that any references need to be tied to how long self
lives; 这意味着任何引用都需要与
self
生存时间联系在一起; the generic lifetime 'a
cannot come into play: 通用生命周期
'a
无法发挥作用:
fn next_run(&self, from: NaiveDateTime) -> Run {
self.entries
.iter()
.map(|entry| Run {
entry,
datetime: entry.recurrence.next_match(from),
})
.min_by(|this, other| this.datetime.cmp(&other.datetime))
.unwrap()
}
Or the explicit version: 或者显式版本:
fn next_run<'b>(&'b self, from: NaiveDateTime) -> Run<'b> { /* ... */ }
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.