为 Iterator::find 提供闭包时的值和引用
Value and references when providing a closure to Iterator::find
我在学习Rust方面还有很长的路要走,但我发现值和引用的使用方式不一致。这可能是我对语言的无知造成的。
例如,这个有效:
let x = (1..100).find(|a| a % 2 == 0);
但 let x = (1..100).find(|a| a > 50);
没有。我不确定 - 为什么?
使用 let x = (1..100).find(|&a| a > 50);
修复了错误,但后来我认为使用 &a
就像要求引用范围中的元素,因此以下应该有效,但它不起作用:
let x = (1..100).find(|&a| *a > 50);
还是不知道为什么!
非平凡模式通常 解构 某些东西,即,将某些东西分解成它的组件。这通常反映了一些 construction 语法,所以它看起来非常相似但实际上是相反的。这种二元论适用于记录、元组、框(一旦正确实现),也适用于引用:
- 表达式
&x
创建对 x
求值结果的引用。这里,&
将 T
类型的值转换为 &T
. 类型的值
- 另一方面,模式
&a
消除了引用,因此a
绑定到后面 引用(注意 a
也可以是另一个更复杂的模式)。此处,&
从 &T
值变为 T
值。
你的例子中的闭包都是&i32 -> bool
1类型。因此它们接受对整数的引用,并且您可以使用该引用(您在第一个示例中这样做,因为算术运算符也为引用重载)或者您可以使用模式 &a
。在后一种情况下,a
是一个 i32
(比较上面的一般解释,用 i32
代替 T
),所以你当然不能进一步取消引用它。
1 这实际上不是真正的类型,但它足够接近我们的目的。
but then I thought using &a is like asking for reference of element from the range
这是你推理的错误部分。在 pattern 中使用 &
恰恰相反 - 它隐式地取消引用匹配的值:
let &a = &10;
// a is 10, not &10 or &&10
你可能已经知道,find()
接受一个满足FnMut(&T) -> bool
的闭包,也就是说,这个闭包接受迭代器的每个元素的引用,所以如果你写(1..100).find(|a| ...)
, a
将是 &i32
.
类型
let x = (1..100).find(|a| a % 2 == 0)
起作用是因为算术运算符被重载以处理引用,因此您可以将 %
应用于引用并且它仍然能够编译。
比较运算符未重载以处理引用,因此您需要从 &i32
获取 i32
。这可以通过两种方式完成,首先,就像您已经做过的那样:
let x = (1..100).find(|&a| a > 50)
这里我们使用 &
模式来隐式取消引用函数参数。相当于这个:
let x = (1..100).find(|a| { let a = *a; a > 50 })
另一种方法是显式取消引用参数:
let x = (1..100).find(|a| *a > 50)
I thought using &a is like asking for reference of element from the range
有时&
用作运算符,有时用作模式匹配。对于闭包参数 (|&a|
),它被用作模式匹配。这意味着变量 a
将在使用时自动取消引用。也相当于do
let x = (1..100).find(|a| *a > 50);
我在学习Rust方面还有很长的路要走,但我发现值和引用的使用方式不一致。这可能是我对语言的无知造成的。
例如,这个有效:
let x = (1..100).find(|a| a % 2 == 0);
但 let x = (1..100).find(|a| a > 50);
没有。我不确定 - 为什么?
使用 let x = (1..100).find(|&a| a > 50);
修复了错误,但后来我认为使用 &a
就像要求引用范围中的元素,因此以下应该有效,但它不起作用:
let x = (1..100).find(|&a| *a > 50);
还是不知道为什么!
非平凡模式通常 解构 某些东西,即,将某些东西分解成它的组件。这通常反映了一些 construction 语法,所以它看起来非常相似但实际上是相反的。这种二元论适用于记录、元组、框(一旦正确实现),也适用于引用:
- 表达式
&x
创建对x
求值结果的引用。这里,&
将T
类型的值转换为&T
. 类型的值
- 另一方面,模式
&a
消除了引用,因此a
绑定到后面 引用(注意a
也可以是另一个更复杂的模式)。此处,&
从&T
值变为T
值。
你的例子中的闭包都是&i32 -> bool
1类型。因此它们接受对整数的引用,并且您可以使用该引用(您在第一个示例中这样做,因为算术运算符也为引用重载)或者您可以使用模式 &a
。在后一种情况下,a
是一个 i32
(比较上面的一般解释,用 i32
代替 T
),所以你当然不能进一步取消引用它。
1 这实际上不是真正的类型,但它足够接近我们的目的。
but then I thought using &a is like asking for reference of element from the range
这是你推理的错误部分。在 pattern 中使用 &
恰恰相反 - 它隐式地取消引用匹配的值:
let &a = &10;
// a is 10, not &10 or &&10
你可能已经知道,find()
接受一个满足FnMut(&T) -> bool
的闭包,也就是说,这个闭包接受迭代器的每个元素的引用,所以如果你写(1..100).find(|a| ...)
, a
将是 &i32
.
let x = (1..100).find(|a| a % 2 == 0)
起作用是因为算术运算符被重载以处理引用,因此您可以将 %
应用于引用并且它仍然能够编译。
比较运算符未重载以处理引用,因此您需要从 &i32
获取 i32
。这可以通过两种方式完成,首先,就像您已经做过的那样:
let x = (1..100).find(|&a| a > 50)
这里我们使用 &
模式来隐式取消引用函数参数。相当于这个:
let x = (1..100).find(|a| { let a = *a; a > 50 })
另一种方法是显式取消引用参数:
let x = (1..100).find(|a| *a > 50)
I thought using &a is like asking for reference of element from the range
有时&
用作运算符,有时用作模式匹配。对于闭包参数 (|&a|
),它被用作模式匹配。这意味着变量 a
将在使用时自动取消引用。也相当于do
let x = (1..100).find(|a| *a > 50);