2017-05-08 54 views
3

我有一个特点它说的Foo任何实施需要提供一种方法bar它返回某种类型的,它实现Iterator<Item = u32>的目的:性状与寿命由一个参数的寿命有界返回迭代

trait Foo { 
    type FooIterator: Iterator<Item = u32>; 
    fn bar(&self) -> FooIterator; 
} 

对于这种情况,我相信默认的生存期限elision意味着由bar返回的迭代器需要独立生存,而不必受限于它正在迭代的Foo的生命周期。 #rust irc上的用户Habnabit建议以下方式说明FooIterator的使用期限低于Foo的使用期限。也就是说,它允许FooIterator的执行,以保持到它来自Foo参考:

trait Foo<'a> { 
    type FooIterator: Iterator<Item = u32> + 'a; 
    fn bar<'b: 'a>(&'b self) -> Self::FooIterator; 
} 

我真正想要的是函数bar需要一个额外的参数的情况下,和FooIterator实现被允许以保留对Foo和附加参数的引用。即FooIterator的生存期由Foo的生存期和附加参数的生存期限定。

我这种想法的直译是

trait Zip {} 
trait Foo<'a, 'c> { 
    type FooIterator: Iterator<Item = u32> + 'a + 'c; 
    // Foo.bar() returns an iterator that has a lifetime less than the Foo 
    fn bar<'b: 'a, 'd: 'c>(&'b self, &'d Zip) -> Self::FooIterator; 
} 

但有人告诉我,有没有“好”的方式做到这一点。实施这个习语最好的方法是什么?上面的代码会做什么?

回答

4

您要找的是associated type constructors,这是一个尚未在Rust中实施的计划功能。随着相关类型构造器,你的代码应该是这样的:

trait Zip {} 
trait Foo { 
    type FooIterator<'a, 'c>: Iterator<Item = u32> + 'a + 'c; 
    // Foo.bar() returns an iterator that has a lifetime less than the Foo 
    fn bar<'a, 'b: 'a, 'c, 'd: 'c>(&'b self, &'d Zip) -> Self::FooIterator<'a, 'c>; 
} 

其实,我不知道那些寿命是必要的,因为&'a T可强制转换为&'b T其中'a: 'b。因此,下面可能是不够好:

trait Zip {} 
trait Foo { 
    type FooIterator<'a, 'c>: Iterator<Item = u32> + 'a + 'c; 
    // Foo.bar() returns an iterator that has a lifetime less than the Foo 
    fn bar<'a, 'c>(&'a self, &'c Zip) -> Self::FooIterator<'a, 'c>; 
} 
+0

每当我问一个Rust问题时,你都必须有一个提示:)有趣的,但它似乎不像关联类型的构造函数将很快在Rust中。解决方法是什么? –

+2

我在看着https://stackoverflow.com/questions/tagged/rust,我并不孤单。 ;)据我所知,没有解决方法,这就是为什么这个功能正在开发过程中。 –

1

根据您想如何使用这个特质,你可以让它通过实现它&'a Struct,而不是为Struct,从而“提升”责任工作寻找从特质到呼叫者的正确生活。

从性状取出寿命注释和改变bar所以需要self,加上相同的寿命的另一种说法:

trait Foo { 
    type FooIterator: Iterator<Item = u32>; 
    fn bar(self, other: Self) -> Self::FooIterator; 
} 

(从性状卸下'a是可能的,因为bar消耗基准代替reborrowing的它 - self因为它已经被移入它,所以不必再有返回值了。)

然后impl它为终生的参考'a

impl<'a> Foo for &'a Vec<u32> { 
    type FooIterator = ...; // something presumably containing 'a 
    fn bar(self, other: Self) -> Self::FooIterator { 
     ... 
    } 
} 

这工作,因为编译器寿命'a限制在一个为其IMPL适用。

Here's a playground link其中bar基本上是围绕.chain()的包装。

现在我忽略了Zip这个特性,因为如何合并它取决于它提供了什么。相反,我想bar只接受与Self相同类型的参数。然而,你也可以添加它,如果你需要的话也许使用相同的技术。