I m 创建像地图这样的数据结构,其中每个价值都提供通过实施海峡恢复其独特钥匙的手段。 钥匙将参照一个或多个具有相应价值的领域(或仅指参考栏目数据,或指临时为例如,在地图上看一个数值时的任何领域)。 关键因素显然需要成为<代码>Ord,以便数据结构能够正确与它们合作。 数据结构目前正在使用一种分类的病媒实施。
当我需要比较寿命不同的关键时,我会遇到终身困难。 例如,一个关键是参数,另一个关键是地图上已经提供的数据,或者一个关键是参数,另一个关键是从一个单独的数据价值参数中检索。 (在我的实际代码中,我并没有在我撰写一份与后一个例子相对应的<代码>replace方法之前处理这个问题,但在为这一问题设立的最低限度再设计方法中,Im还采用了一种简单的<代码>get方法,更像前一个例子;我不肯定我原来的get/code>为何。 我猜想,在我执行后,我改变了做法。
在这里,一些法律被废除:
trait HasKey {
type Key< a>: Ord where Self: a;
fn get_key< a>(& a self) -> Self::Key< a>;
}
struct Data {
id: String,
// more data
}
#[derive(Ord, PartialOrd, Eq, PartialEq)]
struct DataKey< a>(& a str); // might also contain more fields
struct Map<T>(Vec<T>) where T: HasKey;
impl HasKey for Data {
type Key< a> = DataKey< a>;
fn get_key< a>(& a self) -> Self::Key< a> {
DataKey(&self.id)
}
}
impl<T> Map<T> where T: HasKey {
fn compare_keys< a>(left: &T::Key< a>, right: &T::Key< a>) -> std::cmp::Ordering {
left.cmp(right)
}
fn replace< a>(&self, key: &T::Key< a>, value: T) {
Self::compare_keys(key, &value.get_key());
// if keys are equal, replace old value with new value in place
// otherwise remove key and insert value, moving only items in between
}
}
fn main() {
let m = Map(vec![
// test data already sorted; normally Map constructor would sort it
Data { id: "bar".to_string() },
Data { id: "foo".to_string() },
]);
m.replace(DataKey("foo"), Data { id: "foobar".to_string() })
}
编辑们抱怨如下:
error[E0597]: `value` does not live long enough
--> src/main.rs:44:35
43 | fn replace< a>(&self, key: T::Key< a>, value: T) {
| -- ----- binding `value` declared here
| |
| lifetime ` a` defined here
44 | Self::compare_keys(&key, &value.get_key());
| ^^^^^^^^^^^^^^^
| |
| borrowed value does not live long enough
| argument requires that `value` is borrowed for ` a`
...
47 | }
| - `value` dropped here while still borrowed
在经过许多考虑和争执之后,最后在我身上看到了以下事实:要求为<代码>(<><><>>><>> >条码/代码>借款的理由是:<条码>compare_keys在其两个论点中都使用了同一寿命,也就是说,打电话者需要提供与寿命相匹配的论点。 这肯定不是我打算做的事,因此,我试图改写<条码>.compare_keys,以接受不同寿命的论点:
fn compare_keys< a, b>(left: &T::Key< a>, right: &T::Key< b>) -> std::cmp::Ordering {
left.cmp(right)
}
现在,汇编者对电话(left.cmp(right)
提出了同样的申诉,指出 a
must outlive and<>>: b
必须撤销有效期<> a,因此,建议我将其合并为一生(即回到我之前的位置)。 此时此刻,我认识到<代码> Ord requires PartialOrd< Self>
and Eq
(这反过来又要求PartialEq< Self>
和Imttyure that 自我
包括任何终身参数,导致我得出结论: Ord
正在形成一种限制,即我只能比较数据参考寿命相同的钥匙。
这就是我认识到的<代码>。 Ord don t take a para amount such as PartialOrd
do, but as a workaround Itries changing my trait so that it requires keys to be PartialOrd
相反,以便我能够具体指出,比较的类型可能有不同的寿命,例如:
trait HasKey {
type Key< a>: for< b> PartialOrd<Self::Key< b>> where Self: a;
fn get_key< a>(& a self) -> Self::Key< a>;
}
这就要求我提供自己的<条码>部分编码<>和<条码>部分Eq执行,而不是依赖违约执行,而是重三重,而不是一大笔。 我也修改了<代码>compare_keys,改为partial_cmp
,而不是cmp
, 仅限unwrap
。 这最终使汇编者感到高兴。
Playground 与初步代码和评论中的变化/固定内容。
我的问题:
- Did I draw the right conclusion that the errors are effectively caused by
Ord
requiring the lifetime parameters of my key structures to match, or does this actually have some other problem that I missed (but that my workaround still resolves)? - Are there other/better solutions than I came up with? Is there a better way for me to define methods like
replace
? Is there a better way for me to express that keys need to have a total ordering with respect to their values but not their lifetimes?
顺便说一句,我想Ord
,来计算一个通用参数,但自起。 或d
然后Eq
还需要采用一个通用参数(或者也许不是这样,尽管这感觉到是多余的),而且我理解,这不会真正有意义,因为“Eq的整个点是表明一件事情永远平等(除了<条码>部分Eq的要求之外)。 我感到,这里存在某种差距,但我无法表达其定义,因此我认为,这里有一些东西,我要么看不到,要么看不懂。 我失踪了什么?