【问题标题】:Why is "&&" being used in closure arguments?为什么在闭包参数中使用“&&”?
【发布时间】:2017-10-05 07:07:54
【问题描述】:

我有两个关于this example的问题:

let a = [1, 2, 3];

assert_eq!(a.iter().find(|&&x| x == 2), Some(&2));
assert_eq!(a.iter().find(|&&x| x == 5), None);
  1. 为什么在闭包参数中使用&&x 而不仅仅是x?我知道& 正在传递对对象的引用,但是使用它两次是什么意思?

    我不明白文档是怎么说的:

    因为find() 接受一个引用,并且许多迭代器迭代引用,这会导致参数是双重引用的可能令人困惑的情况。您可以在下面的示例中看到这种效果,&&x

  2. 为什么使用Some(&2) 而不是Some(2)

【问题讨论】:

    标签: reference rust borrowing


    【解决方案1】:

    a[i32; 3] 类型;三个i32s 的数组。 [i32; 3] 没有实现 iter 方法,但它确实取消引用到 &[i32]&[i32] implements an iter method 产生一个迭代器。 This iterator 实现 Iterator<Item=&i32>

    它使用&i32 而不是i32,因为迭代器必须处理 any 类型的数组,并且并非所有类型都可以安全地复制。因此,它不是将自身限制为可复制类型,而是通过引用而不是值来迭代元素。

    为所有Iterators 定义find is a method。它使您可以查看每个元素并返回与谓词匹配的元素。问题:如果迭代器产生不可复制的值,那么将值传递给谓词将无法从find 返回它。该值无法重新生成,因为迭代器(通常)不可重绕或可重新启动。因此,find 必须通过引用而不是按值将元素传递给谓词。

    因此,如果您有一个实现Iterator<Item=T> 的迭代器,那么Iterator::find 需要一个接受&T 并返回bool 的谓词。 [i32]::iter 产生一个实现 Iterator<Item=&i32> 的迭代器。因此,在数组迭代器上调用Iterator::find 需要一个接受&&i32 的谓词。也就是说,它将谓词传递给指向相关元素的指针。

    所以如果你写a.iter().find(|x| ..)x 的类型就是&&i32。这不能直接与文字 i322 进行比较。有几种方法可以解决这个问题。一种是显式取消引用x:a.iter().find(|x| **x == 2)。另一种是使用模式匹配来解构双重引用:a.iter().find(|&&x| x == 2)。在这种情况下,这两种方法完全相同做同样的事情。 [1]

    至于为什么使用Some(&2):因为a.iter()&i32的迭代器,不是i32的迭代器。如果您查看Iterator::find 的文档,您会看到Iterator<Item=T> 的文档返回一个Option<T>。因此,在这种情况下,它返回一个 Option<&i32>,因此您需要将其与它进行比较。


    [1]:仅当您谈论非Copy 类型时,差异才有意义。例如,|&&x| .. 不适用于&&String,因为您必须能够将String 从引用后面移出,这是不允许的。但是,|x| **x .. 起作用,因为这只是在不移动任何东西的情况下到达引用内部。

    【讨论】:

    • 谢谢!另外,如果有人不明白什么是"dereference into &[i32]",可以根据&a自动借用数组a作为切片&athis,
    【解决方案2】:

    1) 我认为这本书的解释很好,也许我下面的.cloned() 的例子会有用。但是由于.iter() 会遍历引用,因此您必须另外指定引用,因为find 需要引用。

    2) .iter() 正在迭代引用;因此,您可以找到参考。

    您可以使用.cloned() 来查看如果您不必处理引用会是什么样子:

    assert_eq!(a.iter().cloned().find(|&x| x == 2), Some(2));
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-10-16
      • 1970-01-01
      • 1970-01-01
      • 2018-04-30
      • 1970-01-01
      • 2021-11-17
      • 2012-08-31
      • 2019-09-06
      相关资源
      最近更新 更多