Iterator::findクロージャーに&&を渡さなければならない理由

https://stackoverflow.com/questions/43828013/why-is-being-used-in-closure-arguments

let a = [1, 2, 3];

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

回答

  • a[i32;3]
  • [i32;3]型はiterメソッドが実装されていない
  • [i32;3]型は&[i32]型にdereferenceする ★ 強制型
  • &[i32]型はiterメソッドが実装している
  • iterメソッドは、Iter<i32>型を返す
  • Iter<i32>型は、Iterator<Item=&32>を実装している。Iterator<Item=&i32>実装型
  • Iterator::find<P>(&mut self, predicate: P) -> Option<Self::Item> where P: FnMut(&Self::Item) -> bool
    • Self::Item&i32
    • &Self::Itemとなって綿割れるので&&i32となる
  • i32に戻すには2つのアプローチがある
    • 明示的なdereferenceをする a.iter().find(|x| **x == 2)
    • ダブル参照を破壊するパターンマッチを使う a.iter().find(|&&| x == 2)

パターンマッチによるデリファレンス

let double_ref = &&5;
match double_ref {
    &&val => println!("{} + 3", val),
}

参照

yossan.hatenablog.com