rust 如何在堆栈上创建按值迭代器?

ulydmbyx  于 12个月前  发布在  其他
关注(0)|答案(3)|浏览(111)

我可以在堆中创建一个消费迭代器:

vec![1, 10, 100].into_iter()

字符串
我也可以在栈上创建一个迭代器,借用元素:

[1, 10, 100].iter()


但如果我这样写:

[1, 10, 100].into_iter()


这不是一个消费迭代器,因为[T; _]::into_iter不存在:IntoIterator只为借用的版本(又名切片)实现。有没有一种简单的方法(最好在std库中)在堆栈上创建一个消费迭代器?
我知道[1, 10, 100].iter().cloned()可以做到,但这需要项目是可克隆的。

svujldwt

svujldwt1#

有没有一种简单的方法(最好在std库中)在堆栈上创建一个消费迭代器?

有没有一种简单的方法(最好是在std库中)在堆栈上创建一个消费迭代器?
是的。使用像stacksmallvec这样的crate,它们提供了实现IntoIterator的数组类型。

kfgdxczn

kfgdxczn2#

Rust 1.53(2021版)

从Rust 2021 Edition开始,调用into_iter() on an array总是提供一个消费的按值迭代器。这意味着问题中提供的示例将按照最初的期望工作。

[1, 10, 100].into_iter()

字符串

Rust 1.53(其他版本)

在Rust 2015或2018版本中,上面的代码仍然会解析为(&[1, 10, 100]).into_iter(),但任何其他语法都将提供消费迭代器,无论版本如何。

for x in [1, 10, 100] {
}
IntoIterator::into_iter([1, 10, 100])

的数据

Rust 1.51

std::array::IntoIter为数组提供了一个按值迭代器。这个API与const泛型的基线支持一起提供(参见Rust 1.51公告博客文章)。

std::array::IntoIter::new([1, 10, 100])

Rust < 1.51

你可以有一个宏,它将值 Package 在once迭代器中并将它们链接在一起:

macro_rules! value_iter {
    () => {
        std::iter::empty()
    };
    ($v: expr, $( $rest: expr ), +) => {
        std::iter::once($v).chain(
            value_iter!($($rest),*)
        )
    };
    ($v: expr) => {
        std::iter::once($v)
    };
}


使用:

#[derive(Debug, PartialEq)]
struct Foo;

let it = value_iter![Foo, Foo, Foo];

let all: Vec<_> = it.collect();
assert_eq!(all, vec![Foo, Foo, Foo]);


一个已知的缺点是迭代器不是一个精确大小的迭代器,因此编译器可能会错过一些明显的优化。
Playground

rqenqsqc

rqenqsqc3#

非常丑陋,但技术上可行:

for s in [
    Some(String::from("hello")),
    Some(String::from("goodbye"))
].iter_mut().map(|option| option.take().unwrap()) {
    let s: String = s;
    println!("{}", s);
}

字符串
你可以使用一个宏,以更漂亮的方式实现这一点:

macro_rules! iter {
    [ $( $item:expr ),+ ] => {{
        [ $( Some($item), )+ ]
        .iter_mut()
        .map(|o| o.take().unwrap())
    }};
    // Rule to allow a trailing comma:
    [ $( $item:expr, )+ ] => {{
        iter![ $( $item ),+ ]
    }};
}

fn main() {
    for s in iter![String::from("hello"), String::from("goodbye")] {
        println!("{}", s);
    }
}

相关问题