【问题标题】:Implementing Index trait to return a value that is not a reference实现 Index trait 以返回一个不是引用的值
【发布时间】:2016-08-24 02:50:43
【问题描述】:

我有一个简单的结构,我想为它实现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 typesexpected type &amp;f64, found type f64。作为一个还没有完全理解 Rust 类型系统是如何工作的人,我尝试简单地在表达式上打上&amp;

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

【问题讨论】:

    标签: indexing rust


    【解决方案1】:

    Index trait 旨在将借用的指针返回到 self 的成员(例如 Vec 中的项目)。来自Index 特征的index 方法的签名使得实现它以具有您描述的行为是不切实际的,因为您必须将index 返回的每个值存储在self 中并确保指针在删除 MyStruct 之前保持有效。

    【讨论】:

    • 那么在 MyStruct 上实现一个名为indexat 的方法会更好吗?它接受usize 并返回f64?我还想实现与 Python 切片等效的索引功能(Range 我认为是 rust),这可以通过 ... 语法作为函数参数来实现吗?
    • 您可以编写一个独立的index 方法,但您不能将它与索引语法(x[i])一起使用。范围语法生成标准库提供的类型的值(例如,x..y 生成 Range 值)。
    • 所以基本上我在这里运气不好?哦,好吧,这没什么大不了的,只是学习一门新语言的不同范式。
    【解决方案2】:

    这个用例与Index 的直觉不符。当我看到myStruct[3] 时,我的直觉是,就像数组一样,我得到了一个指向一些已经初始化的数据的指针。 Index 的界面证实了这种直觉。

    我可以看到您可能正在尝试实现的两件事:

    1. 为您的数据结构获取良好的索引语法。

    在这种情况下,我建议不要在实现Index 的前提下,只提供一个返回f64 而不是&amp;f64 的方法。

    impl MyStruct {
        pub fn index(&self, idx: usize) -> f64 {
            self.start + (idx as f64) * self.step
        }
    }
    

    你没有得到运算符,这很好,因为阅读[] 的人会被误导以为他们得到了一个指针。但是你确实得到了你想要的功能。根据您的用例,您可能需要重命名此方法。

    1. MyStruct 传递给具有Index 边界的参数。

    这是有充分理由的。 Index 期望数据在它请求之前就已经存在。您无法生成并返回它,因为index 返回f64,并且您无法在数据结构中生成它并返回指针,因为它不需要&amp;mut self。您必须在调用index 之前填充这些值。一些重新设计将是有序的,重新设计的方向将取决于您问题的更大背景。

    【讨论】:

    • 我想我现在看到我的直觉与 rust 的惯例不同。不过,这个信息有点难找,因为 rust 仍然是一门非常年轻的语言。我的方法基本上是您的第一个建议,尽管我使用了一个我命名为 At&lt;Idx&gt; 的特征,并使用了一个仿照 Index 设计的单一方法 at。如果impl 对应At&lt;Idx&gt; 存在,我已经想出了如何使用Range&lt;Idx&gt; 自动生成At-able,这对于Rust 来说非常方便。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-01-18
    • 2015-03-16
    • 2018-08-02
    • 1970-01-01
    • 1970-01-01
    • 2019-07-22
    • 1970-01-01
    相关资源
    最近更新 更多