代码之家  ›  专栏  ›  技术社区  ›  n. m. could be an AI

fold对它接受的闭包很挑剔

  •  0
  • n. m. could be an AI  · 技术社区  · 6 年前

    let a = [1, 2, 3];
    

    此调用有效:

    let sum = a.iter().fold(0, |acc:  i32, x: &i32| acc + x);
    

    这些不会:

    let sum = a.iter().fold(0, |acc: i32, x: i32| acc + x);
    let sum = a.iter().fold(0, |acc: &i32, x: i32| acc + x);
    

    错误消息是

    error[E0631]: type mismatch in closure arguments
     --> main.rs:8:22
      |
    8 |   let sum = a.iter().fold(0, |acc: &i32, x: i32| acc + x);
      |                      ^^^^    --------------------------- found signature of `for<'r> fn(&'r i32, i32) -> _`
      |                      |
      |                      expected signature of `fn({integer}, &{integer}) -> _`
    
    error: aborting due to previous error
    
    For more information about this error, try `rustc --explain E0631`.
    

    fold . 然而,我看不出它是如何从宣言 折叠

    fn fold<B, F>(self, init: B, f: F) -> B
    where
        F: FnMut(B, Self::Item) -> B
    

    为什么第二个论点应该是 &{integer} {integer} ?

    2 回复  |  直到 6 年前
        1
  •  2
  •   Peter Hall    6 年前

    迭代器中的项是从数组中借用的,也是 &i32 不 i32 . 此窗体有效,因为累加器是所有者,而项目是借用的:

    let sum = a.iter().fold(0, |acc: i32, x: &i32| acc + x);
    

    您可以转换迭代器,使其项被复制而不是被引用,然后第一个表单将起作用:

    let sum = a.iter().copied().fold(0, |acc: i32, x: i32| acc + x);
    

    第三种形式永远行不通。闭包需要能够返回一个新值,用它来更新累加器。蓄能器的类型是 i32号 . 它不能是引用,因为不能从闭包返回引用(原始值将被删除,Rust不会让您返回悬空指针)。

        2
  •  2
  •   Sven Marnach    6 年前

    fold()

    fn fold<B, F>(self, init: B, f: F) -> B
    where
        F: FnMut(B, Self::Item) -> B
    

    B 以及闭合的类型 F FnMut(B, Self::Item) -> B ,这意味着第一个参数的类型与累加器的类型相同,而第二个参数的类型是迭代器的项类型。

    在你的召唤中

    let sum = a.iter().fold(0, |acc: i32, x: &i32| acc + x);
    

    使用item类型的迭代器 &i32 0 ,所以它的类型被推断为 i32 (在没有进一步限定的情况下,这是默认的整数类型)。

    推荐文章