Rust 对于<&燃气轮机;语法不同于常规的生存期界限?
考虑以下代码:Rust 对于<&燃气轮机;语法不同于常规的生存期界限?,rust,Rust,考虑以下代码: trait Trait<T> {} fn foo<'a>(_b: Box<dyn Trait<&'a usize>>) {} fn bar(_b: Box<dyn for<'a> Trait<&'a usize>>) {} trait{} fn foo>){} fn条(_b:Box>){ 函数foo和bar似乎都接受一个框,因为语法被称为高等级特征界限(HRTB),它的引入实
trait Trait<T> {}
fn foo<'a>(_b: Box<dyn Trait<&'a usize>>) {}
fn bar(_b: Box<dyn for<'a> Trait<&'a usize>>) {}
trait{}
fn foo>){}
fn条(_b:Box>){
函数foo
和bar
似乎都接受一个框,因为
语法被称为高等级特征界限(HRTB),它的引入实际上主要是因为闭包
简而言之,foo
和bar
之间的区别在于,在foo()
中,内部usize
引用的生存期由函数的调用方提供,而在bar()
中,相同的生存期由函数本身提供。这种区别对于foo
/bar
的实现非常重要
但是,在这种特殊情况下,当Trait
没有使用类型参数的方法时,这种区别是没有意义的,因此让我们想象一下Trait
如下所示:
trait Trait<T> {
fn do_something(&self, value: T);
}
这不会编译,因为局部变量的生存期严格小于生存期参数指定的生存期(我认为这是很清楚的原因),因此不能调用b.do\u something(&x)
,因为它要求其参数具有生存期'a
,它严格大于x
但是,您可以使用bar
:
fn bar(b: Box<for<'a> Trait<&'a usize>>) {
let x: usize = 10;
b.do_something(&x);
}
这里的闭包必须接受对T
的引用,否则就不可能返回包含在选项中的值(这与迭代器上的filter()
的推理相同)
但是FnOnce(&T)->bool
中的&T
应该有什么生存期呢?记住,我们不在函数签名中指定生命周期,只是因为存在生命周期省略;实际上,编译器在函数签名中为每个引用插入一个生存期参数。在FnOnce(&T)->bool
中应该有一些与&T
相关的生存期。因此,扩展上述签名的最“明显”的方法是:
fn filter<'a, F>(self, f: F) -> Option<T> where F: FnOnce(&'a T) -> bool
然后用&value
调用f
作为参数是完全有效的:我们现在可以选择生存期,因此使用局部变量的生存期是绝对正确的。这就是为什么HRTBs很重要:没有它们,你将无法表达很多有用的模式
您还可以在中阅读关于HRTBs的另一个解释。太棒了!这很清楚,谢谢。希望这将是这个问题的典型答案。作为后续(如果你有一个链接,那就好了,因为我认为这有点超出了我最初问题的范围):为什么它们的等级-特质界限更高?他们和更高级的类型有什么关系吗(我稍微熟悉一点)?@Thirty340是的,我相信他们完全是以HKTs命名的,因为他们确实很像他们。我可以想象,HKT也可以用for
来编写,如果它们可用的话:for Monad
,或者至少,它们有类似的概念——指定无限多的特征边界(或类型,在HKT的情况下),并用一些东西(生命期或类型)参数化。这就是说,HRTBs可以支持类型以及生命周期,只是还没有人提出具体的设计。我认为更高种类的类型与更高等级的类型是正交的。更高级别的类型描述了在类型签名中可以进行量化的位置,而更高级别的类型指的是在类型构造函数上编写多态代码。另请参见:@BurntSushi5哦,我总是把它们彼此混淆:(HRTB是Haskell的QuantifiedConstraints
的锈名吗?
fn bar(b: Box<for<'a> Trait<&'a usize>>) {
let x: usize = 10;
b.do_something(&x);
}
impl<T> Option<T> {
fn filter<F>(self, f: F) -> Option<T> where F: FnOnce(&T) -> bool {
match self {
Some(value) => if f(&value) { Some(value) } else { None }
None => None
}
}
}
fn filter<'a, F>(self, f: F) -> Option<T> where F: FnOnce(&'a T) -> bool
fn filter<F>(self, f: F) -> Option<T> where F: for<'a> FnOnce(&'a T) -> bool