为何&(&i32, &i32)能匹配|&(&x, &y)|与|(&x, &y)|两种闭包?
为什么两种filter闭包写法都能正常工作?
先明确核心前提:
a.iter()/b.iter()生成的迭代器元素是&i32(指向原向量元素的引用)。zip后迭代器的元素类型为(&i32, &i32)。filter的闭包接收的参数是该元素的引用,即类型为&(&i32, &i32)——因为filter不会获取元素所有权,只会传递引用。
写法(A):显式解构外层引用
.filter(|&(&x, &y)| x > 0 && y > 0)
这里的|&(&x, &y)|是逐层显式解构:
- 外层的
|&...|匹配闭包参数&(&i32, &i32),通过&符号解引用外层引用,得到内部元组(&i32, &i32)。 - 元组内的
&x/&y再分别解构每个&i32,最终x和y被推断为i32类型。
写法(B):利用Rust模式匹配的自动解引用规则
.filter(|(&x, &y)| x > 0 && y > 0)
Rust的模式匹配有一个实用规则:当参数是引用类型,但你提供的模式不是引用模式(比如这里的元组模式(&x, &y)本身不是&...形式),编译器会自动对参数进行一次解引用,再尝试匹配模式。
具体到这个例子:
- 闭包参数是
&(&i32, &i32),编译器自动解引用一次,得到(&i32, &i32)。 - 接下来的逻辑和写法(A)完全一致:元组内的
&x/&y解构&i32,得到i32类型的x和y。
本质上,写法(B)是让编译器帮你省略了显式解引用外层&的步骤,最终效果和(A)完全相同。
等价验证
你可以把写法(B)拆成手动解构的形式,效果完全一致:
.filter(|arg: &(&i32, &i32)| { let (&x, &y) = arg; // 手动解引用并解构,等同于写法(B)的自动处理 x > 0 && y > 0 })
内容的提问来源于stack exchange,提问作者StrausMG
相关产品推荐
相关产品推荐

