【问题标题】:IntoIterator as a function argument doesn't accept adapter structIntoIterator 作为函数参数不接受适配器结构
【发布时间】:2019-09-29 20:14:11
【问题描述】:

我想要一个函数,它接受&IntoIterator<Item=u32>,所以我可以将&Vec<u32> 和迭代器的适配器结构(如MapFilter 和任何其他的,我相信它们都实现@ 987654325@)

所以我有一个类似的功能

pub fn f<'a, T>(it_src: &'a T) -> u32
where &'a T: IntoIterator<Item = u32> {
    let it = it_src.into_iter();
    let result: u32;
    // more more usage
    result
}

这就是我尝试使用它的方式(相同的签名,但不同的名称)

pub fn f_with_feature()<'a, T>(it_src: &'a T) -> u32
where &'a T: IntoIterator<Item = u32> {
    let adjusted_values = it_src.into_iter()
        .map(|e| adjust(e));
    f(&adjusted_values)
}

我得到的是一个错误

 error[E0308]: mismatched types
  --> src\main.rs:14:7
   |
14 |     f(&adjusted_values)
   |       ^^^^^^^^^^^^^^^^ expected type parameter, found struct `std::iter::Map`
   |
   = note: expected type `&T`
              found type `&std::iter::Map<<&T as std::iter::IntoIterator>::IntoIter, [closure@src\main.rs:13:14: 13:27]>`

Map 和 T 不匹配怎么办?

另外,我想出了一个想法,通过静态调度传递迭代器的适配器并不是一个好主意,因为用于生成 Map 的每个其他闭包都会创建一个新的函数特化。尽管我已经看到大多数时候静态调度方法在 Rust 中是惯用的。如何处理这种情况?

【问题讨论】:

    标签: rust iterator


    【解决方案1】:

    我认为您希望在 T 上(而不是在 &amp;'a T 上)设置 trait bound。所以我猜你实际上想要以下内容:

    pub fn f<'a, T>(it_src: &'a T) -> u32
    where T: IntoIterator<Item = u32> {
        let it = it_src.into_iter();
        let result: u32 = 1;
        // more more usage
        result
    }
    
    pub fn f_with_feature<'a, T>(it_src: &'a T) -> u32
    where T: IntoIterator<Item = u32> {
        let adjusted_values = it_src.into_iter()
            .map(|e| adjust(e));
        f(&adjusted_values)
    }
    

    这就引出了下一个问题:IntoIteratorinto_iter 消耗了self,这意味着如果你只借用it_src,就不能调用it_src.into_iter

    所以如果你真的想使用into_iter,你可以试试这个:

    pub fn f<T>(it_src: T) -> u32
    where T: IntoIterator<Item = u32> {
        let it = it_src.into_iter();
        let result: u32 = 1;
        // more more usage
        result
    }
    
    pub fn f_with_feature<T>(it_src: T) -> u32
    where T: IntoIterator<Item = u32> {
        let adjusted_values = it_src.into_iter()
            .map(|e| adjust(e));
        f(adjusted_values)
    }
    

    但是,以上要求您将值分别移动到 f 中。 f_with_feature.

    根据我的经验,只需使用迭代器(必要时在调用站点进行转换),就可以得到简单、直接的解决方案:

    pub fn f<T>(it_src: T) -> u32
    where T: Iterator<Item = u32> {
        let it = it_src.into_iter();
        let result: u32 = 1;
        // more more usage
        result
    }
    
    pub fn f_with_feature<T>(it_src: T) -> u32
    where T: Iterator<Item = u32> {
        let adjusted_values = it_src.into_iter()
            .map(|e| adjust(e));
        f(adjusted_values)
    }
    

    【讨论】:

    • 我已经转向了迭代器方法,但是很遗憾强制传递一个迭代器,而不是 &Vec<_>,它实现了 IntoIterator 并且不消耗向量
    猜你喜欢
    • 2014-02-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-08-06
    • 1970-01-01
    • 1970-01-01
    • 2018-11-10
    • 1970-01-01
    相关资源
    最近更新 更多