在学习rcore代码过程中突发好奇迭代器的find()原理
从源代码注释可知,find 根据闭包作为参数,然后bool类型,闭包捕捉迭代器的参数类型为迭代器成员类型
/// Searches for an element of an iterator that satisfies a predicate.
///
/// `find()` takes a closure that returns `true` or `false`. It applies
/// this closure to each element of the iterator, and if any of them return
/// `true`, then `find()` returns [`Some(element)`]. If they all return
/// `false`, it returns [`None`].
///
/// `find()` is short-circuiting; in other words, it will stop processing
/// as soon as the closure returns `true`.
///
/// Because `find()` takes a reference, and many iterators iterate over
/// references, this leads to a possibly confusing situation where the
/// argument is a double reference. You can see this effect in the
/// examples below, with `&&x`.
///
/// If you need the index of the element, see [`position()`].
///
/// [`Some(element)`]: Some
/// [`position()`]: Iterator::position
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// let a = [1, 2, 3];
///
/// assert_eq!(a.iter().find(|&&x| x == 2), Some(&2));
///
/// assert_eq!(a.iter().find(|&&x| x == 5), None);
/// ```
///
/// Stopping at the first `true`:
///
/// ```
/// let a = [1, 2, 3];
///
/// let mut iter = a.iter();
///
/// assert_eq!(iter.find(|&&x| x == 2), Some(&2));
///
/// // we can still use `iter`, as there are more elements.
/// assert_eq!(iter.next(), Some(&3));
/// ```
///
/// Note that `iter.find(f)` is equivalent to `iter.filter(f).next()`.
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_do_not_const_check]
fn find<P>(&mut self, predicate: P) -> Option<Self::Item>
where
Self: Sized,
P: FnMut(&Self::Item) -> bool,
{
#[inline]
fn check<T>(mut predicate: impl FnMut(&T) -> bool) -> impl FnMut((), T) -> ControlFlow<T> {
move |(), x| {
if predicate(&x) { ControlFlow::Break(x) } else { ControlFlow::Continue(()) }
}
}
self.try_fold((), check(predicate)).break_value()
}
以上源码主要难点在于:
1,predicate 类型为: FnMut(&Self::Item) -> bool
2,check 函数类型,输入参数为 predicate类型,返回类型为
FnMut((), T) -> ControlFlow<T>
也就是 check函数的原型是 将 FnMut(&Self::Item) -> bool转化为
FnMut((), &Self::Item) -> ControlFlow<&Self::Item>
fold函数是成员展开,如果配到true为则返回当前Item, 否则继续下一个成员展开
check函数的难点是函数原型