为什么 Iterator::take_while 获得迭代器的所有权? [英] Why does Iterator::take_while take ownership of the iterator?

查看:34
本文介绍了为什么 Iterator::take_while 获得迭代器的所有权?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我觉得很奇怪 迭代器::take_while 获取迭代器的所有权.能够获取满足某些功能的第一个 x 元素,但仍然保留原始迭代器中可用的其余元素,这似乎是一个有用的功能.

I find it odd that Iterator::take_while takes ownership of the iterator. It seems like a useful feature to be able to take the first x elements which satisfy some function but still leave the rest of the elements available in the original iterator.

我知道这与 take_while 的惰性实现不兼容,但仍然感觉有用.这只是被判断为不足以包含在标准库中,还是有其他一些我没有看到的问题?

I understand that this is incompatible with a lazy implementation of take_while, but still feels useful. Was this just judged not useful enough to include in the standard library, or is there some other problem I'm not seeing?

推荐答案

为了效率,所有迭代器适配器都采用原始迭代器的值.此外,获得原始迭代器的所有权可避免在不必要时处理生命周期.

All the iterator adapters take the original iterator by value for efficiency's sake. Additionally, taking ownership of the original iterator avoids having to deal with lifetimes when it isn't necessary.

如果您希望保留对原始迭代器的访问权限,可以使用 by_ref.这引入了一层间接,但程序员会在需要该功能时选择加入额外的工作:

If you wish to retain access to the original iterator, you can use by_ref. This introduces one level of indirection, but the programmer chooses to opt into the extra work when the feature is needed:

fn main() {
    let v = [1, 2, 3, 4, 5, 6, 7, 8];
    let mut i1 = v.iter();
    for z in i1.by_ref().take_while(|&&v| v < 4) {
        //     ^^^^^^^^^
        println!("Take While: {}", z);
    }

    for z in i1 {
        println!("Rest: {}", z);
    }
}

有输出

Take While: 1
Take While: 2
Take While: 3
Rest: 5
Rest: 6
Rest: 7
Rest: 8

Iterator::by_ref 之所以有效,是因为对于迭代器的任何可变引用都有一个 Iterator 的实现:

Iterator::by_ref works because there's an implementation of Iterator for any mutable reference to an iterator:

impl<'_, I> Iterator for &'_ mut I
where
    I: Iterator + ?Sized, 

这意味着您还可以使用可变引用.括号需要优先:

This means that you can also take a mutable reference. The parenthesis are needed for precedence:

for z in (&mut i1).take_while(|&&v| v < 4)


您是否注意到 4 丢失了?那是因为一旦 take_while 选择一个值并决定不使用它,它就无处可放回去".把它放回去需要选择更多存储空间和比总是需要的速度慢.


Did you note that 4 was missing? That's because once take_while picks a value and decides to not use it, there's nowhere for it to "put it back". Putting it back would require opting into more storage and slowness than is always needed.

我使用了 itertools crate 来处理这样的情况,特别是 take_while_ref:

I've used the itertools crate to handle cases like this, specifically take_while_ref:

use itertools::Itertools; // 0.9.0

fn main() {
    let v = [1, 2, 3, 4, 5, 6, 7, 8];
    let mut i1 = v.iter();
    for z in i1.take_while_ref(|&&v| v < 4) {
        //     ^^^^^^^^^^^^^^^
        println!("Take While: {}", z);
    }

    for z in i1 {
        println!("Rest: {}", z);
    }
}

Take While: 1
Take While: 2
Take While: 3
Rest: 4
Rest: 5
Rest: 6
Rest: 7
Rest: 8

这篇关于为什么 Iterator::take_while 获得迭代器的所有权?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆