我有一个简单的结构,我想实现Index
,但作为Rust的新手,我在借用检查器方面遇到了许多麻烦。我的结构非常简单,我想让它存储起始值和步长值,然后当由usize
索引时它应该返回start + idx * step
:
pub struct MyStruct {
pub start: f64,
pub step: f64,
}
我的直觉是,我能够采用Index
的签名并插入我的类型:
impl Index<usize> for MyStruct {
type Output = f64;
fn index(&self, idx: usize) -> &f64 {
self.start + (idx as f64) * self.step
}
}
这会导致错误mismatched types
说expected type &f64, found type f64
。作为尚未完全理解Rust类型系统如何工作的人,我尝试简单地在表达式上单击&
:
fn index(&self, idx: usize) -> &f64 {
&(self.start + (idx as f64) * self.step)
}
这现在告诉我borrowed value does not live long enough
,所以它可能需要一个生命周期变量?
fn index<'a>(&self, idx: usize) -> &'a f64 {
&(self.start + (idx as f64) * self.step)
}
错误是相同的,但现在注释中提到的是lifetime 'a
而不是lifetime #1
,所以我猜这不是必要的,但此时此刻我感觉自己就像我一样卡住。我很困惑,大多数语言的这种简单练习在Rust中很难实现,因为我想做的就是从恰好位于引用后面的函数返回一个计算。我应该如何为一个简单的结构实现Index
,其中值是按需计算的?
答案 0 :(得分:3)
Index
特征旨在将借用的指针返回给self
的成员(例如Vec
中的项目)。来自index
特征的Index
方法的签名使得实现它以实现您描述的行为是不切实际的,因为您必须将index
返回的每个值存储在{self
中。 1}}并确保指针在MyStruct
被删除之前保持有效。
答案 1 :(得分:1)
此用例与Index
的直觉不符。当我看到myStruct[3]
时,我的直觉是,就像数组一样,我得到了一些已经初始化的数据的指针。 Index
的界面证实了这种直觉。
我可以看到你可能想要实现的两件事:
在这种情况下,我建议不要实施Index
的前提,只提供一个返回f64
而不是&f64
的方法。
impl MyStruct {
pub fn index(&self, idx: usize) -> f64 {
self.start + (idx as f64) * self.step
}
}
你没有得到操作员,这很好,因为有人读[]
会误导他们认为他们得到了一个指针。但是你确实得到了你想要的功能。根据您的使用情况,您可能需要重命名此方法。
MyStruct
传递给Index
边界的参数。这很有道理。 Index
期望数据在它要求之前存在。您无法生成并返回它,因为index
会返回f64
,并且您无法在数据结构中生成它并返回指针,因为它没有&mut self
1}}。您必须在调用index
之前填充这些值。一些重新设计将是有序的,重新设计的方向将取决于您的问题的更大背景。