Rust 国际热核聚变实验堆和国际热核聚变实验堆有什么区别?
我正在编写包含以下代码片段的教程:Rust 国际热核聚变实验堆和国际热核聚变实验堆有什么区别?,rust,Rust,我正在编写包含以下代码片段的教程: // Vec example let vec1 = vec![1, 2, 3]; let vec2 = vec![4, 5, 6]; // `iter()` for vecs yields `&i32`. Destructure to `i32`. println!("2 in vec1: {}", vec1.iter() .any(|&x| x == 2)); // `into_iter()` for vecs yields `i3
// Vec example
let vec1 = vec![1, 2, 3];
let vec2 = vec![4, 5, 6];
// `iter()` for vecs yields `&i32`. Destructure to `i32`.
println!("2 in vec1: {}", vec1.iter() .any(|&x| x == 2));
// `into_iter()` for vecs yields `i32`. No destructuring required.
println!("2 in vec2: {}", vec2.into_iter().any(| x| x == 2));
// Array example
let array1 = [1, 2, 3];
let array2 = [4, 5, 6];
// `iter()` for arrays yields `&i32`.
println!("2 in array1: {}", array1.iter() .any(|&x| x == 2));
// `into_iter()` for arrays unusually yields `&i32`.
println!("2 in array2: {}", array2.into_iter().any(|&x| x == 2));
我完全搞糊涂了——对于Vec
来说,从iter
返回的迭代器产生引用,从返回到iter
的迭代器产生值,但是对于数组,这些迭代器是相同的吗
这两种方法的用例/API是什么?.into_iter()
不是为数组本身实现的,而是仅为&[]
实现的。比较:
impl<'a, T> IntoIterator for &'a [T]
type Item = &'a T
implTL;医生:
返回到iter
的迭代器可能会产生T
、&T
或&mut T
中的任意一个,具体取决于上下文
- 按照惯例,
iter
返回的迭代器将产生&T
- 按照惯例,
iter\u mut
返回的迭代器将产生&mut T
第一个问题是:“iter的是什么?”
into_iter
来自:
每种变体略有不同
这个函数直接使用Vec
及其迭代器(T
):
而这个,
impl;
fn into_iter(self)->slice::IterMutI(一个铁锈新手)从谷歌来到这里,寻求一个其他答案无法提供的简单答案。这是一个简单的答案:
iter()
通过引用迭代项目
into_iter()
迭代这些项,将它们移动到新范围中
iter_mut()
迭代项目,为每个项目提供可变引用
因此,my|vec{…}
中x的本质上等同于my|vec.into_iter()。对于每个(|x|…)
-两者都将my|vec
的元素移动到范围内
如果您只需要“查看”数据,请使用iter
;如果您需要编辑/修改数据,请使用iter\u mut
;如果您需要将数据赋予新的所有者,请使用导入iter
这很有帮助:
将此设置为社区维基,以便如果我犯了任何错误,Rust pro可以编辑此答案。我认为还有一些需要澄清的地方。集合类型,例如Vec
和VecDeque
,具有到iter
方法中,该方法生成T
,因为它们实现了到迭代器中。没有什么可以阻止我们创建一个类型Foo
,如果对它进行迭代,它将不会生成T
,而是生成另一个类型U
。也就是说,Foo
实现了IntoIterator
实际上,std
中有一些例子:&Path
IntoIterator
和&UnixListener
IntoIterator
国际热核试验堆和国际热核试验堆之间的差异
回到原来的问题,即到iter
和iter
之间的区别。与其他人指出的类似,区别在于,进入iter
是一种必需的方法,它可以产生中指定的任何类型。通常,如果一个类型在迭代器
中实现了,按照惯例,它还有两个特别的方法:iter
和iter\u mut
,分别产生&I
和&mut I
这意味着我们可以创建一个函数,通过使用特征绑定来接收一个类型,该类型具有到iter
方法(即,它是一个iterable):
fn process_iterable<I: IntoIterator>(iterable: I) {
for item in iterable {
// ...
}
}
如果v.iter()
等同于&v
,因为两者都实现了IntoIterator
,那么为什么Rust同时提供这两种功能呢?这是人体工程学的。在for
循环中,使用&v
比v.iter()
更简洁;但在其他情况下,v.iter()
比(&v)清楚得多
何时向iter提供(实施)和类型的iter
方法
如果类型只有一种“方法”可以迭代,那么我们应该同时实现这两种方法。然而,如果有两种或两种以上的方法可以迭代,我们应该为每种方法提供一个特别的方法
例如,String
既不向iter
提供,也不向iter
提供,因为迭代它有两种方法:以字节为单位迭代它的表示,或以字符为单位迭代它的表示。相反,它提供了两种方法:迭代字节和迭代字符,作为iter
方法的替代方法
*从技术上讲,我们可以通过创造一种特质来做到这一点。但是我们需要为我们想要使用的每种类型impl
这个特性。同时,std
中的许多类型已经实现了IntoIteratorIntoIterator
也实现了&'a mut[T]
,因此它可以将对象移出数组。我认为这与以下事实有关:IntoIter
返回结构没有生存期参数,而Itermut
意味着可以更改值,而不是将其移出。@rodrigo让mut a=[“abc.to_string()”;a、 进入| iter().map(|x |{*x})代码>=>“错误:无法移出借用的内容”是的,我认为你是对的,不能从数组中移出值。但是,我仍然认为,作为库的一部分,应该可以使用不安全的Rust实现一种ArrayIntoIter
struct。。。也许不值得,因为你无论如何都应该在这些情况下使用Vec
。。。这就是为什么array.into_iter
返回&T
——因为自动将其转换为&array.into_iter
——是这样的话,我不明白这与移动值或不移动值有什么关系。或者,正如@rodrigo所说,你之所以获得引用,仅仅是因为(出于某种原因)你无法移动值
pub trait IntoIterator
where
<Self::IntoIter as Iterator>::Item == Self::Item,
{
type Item;
type IntoIter: Iterator;
fn into_iter(self) -> Self::IntoIter;
}
impl<T> IntoIterator for Vec<T>
impl<'a, T> IntoIterator for &'a Vec<T>
impl<'a, T> IntoIterator for &'a mut Vec<T>
impl<T> IntoIterator for Vec<T> {
type Item = T;
type IntoIter = IntoIter<T>;
fn into_iter(mut self) -> IntoIter<T> { /* ... */ }
}
impl<'a, T> IntoIterator for &'a Vec<T> {
type Item = &'a T;
type IntoIter = slice::Iter<'a, T>;
fn into_iter(self) -> slice::Iter<'a, T> { /* ... */ }
}
impl<'a, T> IntoIterator for &'a mut Vec<T> {
type Item = &'a mut T;
type IntoIter = slice::IterMut<'a, T>;
fn into_iter(self) -> slice::IterMut<'a, T> { /* ... */ }
}
fn process_iterable<I: IntoIterator>(iterable: I) {
for item in iterable {
// ...
}
}
let v = vec![1, 2];
// Below is equivalent to: `for item in v.iter() {`
for item in &v {
println!("{}", item);
}
let v = vec![1, 2];
let a: Vec<i32> = v.iter().map(|x| x * x).collect();
// Although above and below are equivalent, above is a lot clearer than below.
let b: Vec<i32> = (&v).into_iter().map(|x| x * x).collect();
let mut v = vec![1, 2];
// Below is equivalent to: `for item in v.iter_mut() {`
for item in &mut v {
*item *= 2;
}