首页 文章

如何获取引用的IntoIterator并返回对修改后的值的盒装迭代器?

提问于
浏览
-4

我已经掌握了Rust生命周期的基础知识以及如何使用迭代器,但是仍然有一些麻烦来定义一个函数,它接受一个可迭代的元组并返回一个也在堆上分配的可迭代元组 .

(我知道"iterable"在Rust中没有任何意义但是我仍然会使用它而不是 IntoInterator

use std::iter::{once, repeat};

fn foo<'a, I>(costs: I) -> Box<Iterator<Item = &'a (i32, f32)>>
where
    I: IntoIterator<Item = &'a (usize, f32)>,
{
    let preliminary_examination_costs = once(10.0).chain(repeat(20.0));
    let id_assignment_costs = once(10.0).chain(repeat(20.0));
    let batch_fixed = once(10.0).chain(repeat(0.0));
    let temp: Vec<(usize, &(i32, f32))> = costs.into_iter().enumerate().collect();
    temp.sort_by_key(|&(_, &(n, cost))| n);
    Box::new(temp.into_iter().map(|(i, &(n, cost))| {
        (
            i,
            cost + preliminary_examination_costs.next().unwrap()
                + id_assignment_costs.next().unwrap() + batch_fixed.next().unwrap(),
        )
    }))
}

playground

这是错误:

error[E0277]: the trait bound `std::vec::Vec<(usize, &(i32, f32))>: std::iter::FromIterator<(usize, &'a (usize, f32))>` is not satisfied
  --> src/main.rs:10:73
   |
10 |     let temp: Vec<(usize, &(i32, f32))> = costs.into_iter().enumerate().collect();
   |                                                                         ^^^^^^^ a collection of type `std::vec::Vec<(usize, &(i32, f32))>` cannot be built from an iterator over elements of type `(usize, &'a (usize, f32))`
   |
   = help: the trait `std::iter::FromIterator<(usize, &'a (usize, f32))>` is not implemented for `std::vec::Vec<(usize, &(i32, f32))>`

error[E0271]: type mismatch resolving `<[closure@src/main.rs:12:35: 18:6 preliminary_examination_costs:_, id_assignment_costs:_, batch_fixed:_] as std::ops::FnOnce<((usize, &(i32, f32)),)>>::Output == &(i32, f32)`
  --> src/main.rs:12:5
   |
12 | /     Box::new(temp.into_iter().map(|(i, &(n, cost))| {
13 | |         (
14 | |             i,
15 | |             cost + preliminary_examination_costs.next().unwrap()
16 | |                 + id_assignment_costs.next().unwrap() + batch_fixed.next().unwrap(),
17 | |         )
18 | |     }))
   | |_______^ expected tuple, found &(i32, f32)
   |
   = note: expected type `(usize, f32)`
              found type `&(i32, f32)`
   = note: required because of the requirements on the impl of `std::iter::Iterator` for `std::iter::Map<std::vec::IntoIter<(usize, &(i32, f32))>, [closure@src/main.rs:12:35: 18:6 preliminary_examination_costs:_, id_assignment_costs:_, batch_fixed:_]>`
   = note: required for the cast to the object type `std::iter::Iterator<Item=&(i32, f32)>`

1 回答

  • 1

    在遇到问题时创建MCVE非常有用,并且's something I encourage all learners to undertake. Here'是一个镜像代码的MCVE:

    fn foo<'a, I>(costs: I) -> Box<Iterator<Item = &'a i32>>
    where
        I: IntoIterator<Item = &'a i32>,
    {
        Box::new(costs.into_iter().map(|i| i + 1))
    }
    
    error[E0271]: type mismatch resolving `<[closure@src/main.rs:5:36: 5:45] as std::ops::FnOnce<(&'a i32,)>>::Output == &i32`
     --> src/main.rs:5:5
      |
    5 |     Box::new(costs.into_iter().map(|i| i + 1))
      |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected i32, found &i32
      |
      = note: expected type `i32`
                 found type `&i32`
      = note: required because of the requirements on the impl of `std::iter::Iterator` for `std::iter::Map<<I as std::iter::IntoIterator>::IntoIter, [closure@src/main.rs:5:36: 5:45]>`
      = note: required for the cast to the object type `std::iter::Iterator<Item=&i32>`
    

    您正在接受引用,然后根据引用创建一个全新的值 . 这意味着返回类型不再是引用,因此不支持您的函数签名 . 你需要改变它:

    fn foo<'a, I>(costs: I) -> Box<Iterator<Item = i32>>
    

    这将解锁另一个错误,因为编译器对 I::IntoIter 的具体类型了解不够:

    error[E0310]: the associated type `<I as std::iter::IntoIterator>::IntoIter` may not live long enough
     --> src/main.rs:6:5
      |
    6 |     Box::new(costs.into_iter().map(|i| i + 1))
      |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
      |
      = help: consider adding an explicit lifetime bound `<I as std::iter::IntoIterator>::IntoIter: 'static`...
    note: ...so that the type `std::iter::Map<<I as std::iter::IntoIterator>::IntoIter, [closure@src/main.rs:6:36: 6:45]>` will meet its required lifetime bounds
     --> src/main.rs:6:5
      |
    6 |     Box::new(costs.into_iter().map(|i| i + 1))
      |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    

    我们按照建议做并添加 'static 界限:

    fn foo<'a, I>(costs: I) -> Box<Iterator<Item = i32>>
    where
        I: IntoIterator<Item = &'a i32>,
        I::IntoIter: 'static,
    {
        Box::new(costs.into_iter().map(|i| i + 1))
    }
    

    也可以看看:


    error[E0277]: the trait bound `std::vec::Vec<(usize, &(i32, f32))>: std::iter::FromIterator<(usize, &'a (usize, f32))>` is not satisfied
    

    此错误是因为您有一个 (usize, &'a (usize, f32)) 的迭代器,并且您正尝试将它们转换为 (usize, &(i32, f32)) . 你不能转换这样的类型 .

相关问题