参考如何在绑定表达式中的模式中工作? [重复]

问题描述 投票:0回答:1

我在Rust书中看到了下面的例子。

for &item in list.iter() {
    if item > largest {
        largest = item;
    }
}

我想这意味着list.iter()返回对列表中元素的引用,因此&item但是在将它与最大数字进行比较时,为什么我们不使用*item?此外,当我在第一行将&item更改为item时,我被编译器强制在第2行和第3行使用*item

我在网上看到了另一个例子。

(0..).map(|x| x * x)
    .take_while(|&x| x <= limit)
    .filter(|x| is_even(*x))

在这里take_while的封闭接受&x但直接使用xfilter的封闭在没有参考的情况下接受x但是将*x传递给is_even

那么这在Rust中是如何工作的?

reference rust iterator
1个回答
4
投票

你在这里看到的是所谓的解构。这是一个可以拆分带有图案的结构的功能。

你可能已经看过像let (a, b) = returns_a_tuple();这样的东西了。在这里,元组被解构。您还可以解构引用:

// The comments at the end of the line tell you the type of the variable
let i = 3;                // : i32
let ref_i = &i;           // : &i32
let ref_ref_i = &ref_i;   // : &&i32

let &x = ref_i;       // : i32
let &y = ref_ref_i;   // : &i32
let &&z = ref_ref_i;  // : i32

// All of these error because we try to destructure more layers of references
// than there are.
let &a = i;
let &&b = ref_i;
let &&&c = ref_ref_i;

这具有反直觉效果,即您在模式中添加的&越多,变量类型的&就越少。但它在解构的上下文中确实有意义:当你已经提到模式中的结构时,结构将不再存在于绑定变量中。

(值得注意的是,这种“解构引用”仅适用于Copy的裁判类型。否则你将获得“无法摆脱借来的内容”的错误。)


那你的for循环和闭包有什么关系呢?事实证明:模式无处不在。 for循环中forin之间的槽是一个模式,函数和闭包的参数也是模式!这有效:

// Destructuring a tuple in the for loop pattern
let v = vec![3];
for (i, elem) in v.iter().enumerate() {}

// Destructuring an array in the function argument (works the same for closures)
fn foo([x, y, z]: [f32; 3]) {}

我想这意味着list.iter()返回对列表中元素的引用

究竟。

...因此&item

“因此”在这里不正确。此代码的作者不希望使用对项目的引用,而是使用真正的值。所以他们在模式中添加了&来消除参考。

但是,与最大数字相比,为什么我们不使用*item

是的,因为已经通过解构模式删除了引用。

此外,当我在第一行将&item更改为item时,我被编译器强制在第2行和第3行使用*item

是的,因为现在模式不再破坏参考,所以item再次参考。这是所有这一切的基本要点:大多数情况下,您可以通过添加&删除模式中的引用,或者您可以通过添加*来使用变量时删除引用。

在这里take_while的封闭接受&x但直接使用xfilter的封闭在没有参考的情况下接受x但是将*x传递给is_even

现在应该清楚为什么会这样,对吧? take_while闭包通过模式中的解构来移除引用,而filter闭包通过标准解除引用来完成它。


你可以在this chapter of the book上阅读更多关于这一切的信息。

© www.soinside.com 2019 - 2024. All rights reserved.