I assume that lhs means left hand side and rhs means right hand side. But why does the closure has two parameters? Where does the second parameter came from?

As far as I understand this code .enumerate() returns a tuple with a number and the corresponding point. Maybe I'm already wrong at this point.

This code involves iterators. The method in question is Iterator::min_by. The .enumerate() method creates an iterator of tuples. The min_by method finds the â€śminimumâ€ť item, itâ€™s a variant of the Iterator::min method, but it doesnâ€™t require an Ord implementation. Instead it expects a closure that serves as an ad-hoc implementation of a Ord::cmp-style function. Hence the signature is the same as Ord::cmp, i.e. fn(&T, &T) -> Ordering where T is the type of the item.

In this particular case, points.iter().enumerate() is an iterator of (usize, &Point) pairs, the |lhs, rhs| lhs.1.x.partial_cmp(&rhs.1.x).unwrap() now compares these (usize, &Point) items by considering their Point's x-coordinate only (which is an f32 value).

The two arguments are two items of the iterator that ought to be compared. The min_by method will operate by going through the whole iterator linearly and always keeping track of the item thatâ€™s currently minimal among all the visited items so far. For each new item, hence the currently minimal item needs to be compared to the new item to see if perhaps that new item is smaller. In order to do this, min_by will call the provided closure and determine the ordering relation of these two items based on the result of type Ordering.

So min_by() loops over the iterator by itself (there is no for loop, foreach or next) and lhs is the current element and rhs is the next element of the iterator

in the next iteration lhs is consumed, rhs becomes lhs and the next item becomes rhs

min_by() returns a Result of the minimal value which is unpacked by .expect()

the only happens if the previous rhs was actually found to be smaller than the previous lhs. Otherwise previous lhs and new lhs stay the same. Also note that the documentation doesnâ€™t really guarantee the exact calls to cmp, in particular the arguments could also be flipped, thatâ€™s an implementation detail. The closure is â€“ basically â€“ expected to behave according to the rules/axioms specified in the Ord/PartialOrd docs, i.e. for the closure f, it expects, for all values x, y and z:

calling f(&x, &y) is deterministic (always produces the same result only depending on x/y), at least for the duration of the min_by() call/iteration, and for the elements of the iterator

if f(&x, &y).is_le() && f(&y, &z).is_le(), then f(&x, &z).is_le() must be true as well

Itâ€™s an Option, but other than that basically, yes. None should only happen for an empty iterator.

One equivalent, but direct implementation of min_by (for simplicity written as a free-standing function, not a method) would be the following

use std::cmp::Ordering;
fn min_by<T>(
mut iter: impl Iterator<Item = T>,
mut cmp: impl FnMut(&T, &T) -> Ordering,
) -> Option<T> {
// initially, the first item is the â€ścurrent minimumâ€ť
let mut current_min = iter.next()?; // returns None if the iterator is empty
for item in iter {
// If both are comparing â€śequalâ€ť, keep the current minimum.
// Only if the next item is comparing as (strictly) â€śsmallerâ€ť
// (i.e. the current minimum is (strictly) â€śgreaterâ€ť)
// update the current minimum accordingly.
if cmp(¤t_min, &item) == Ordering::Greater {
current_min = item
}
}
Some(current_min)
}