#prog #моё
У метода
Iterator::all — который возвращает, удовлетворяют ли все элементы в итераторе переданному предикату — есть вот такая строчка в документации:
An empty iterator returns true.
Более того, аналогичное утверждение есть и в документации
метода allMatch на Java Stream API, и в документации встроенной функции
all в Python, и в документации
IEnumerable.All в C#. Некоторые странные люди утверждают, что
all на пустой последовательности должен возвращать
false — дескать, нет значений — не возможности определить значения.
Я здесь для того, чтобы сказать, что эти люди неправы.
Условный
all(seq, pred), где
seq — это последовательность
a1, a2, ..., an, вычисляет значение
pred(a1)∧ pred(a2) ∧ ... ∧ pred(an) (∧ — символ коньюкции, который в ЯП часто называют
&&). Коньюкция — операция коммутативная и ассоциативная, поэтому если последовательность
s является конкатенацией последовательностей
a = a1, a2, ..., an и
b = b1, b2, ..., bn, то мы можем переставить скобки и посчитать
all(s, pred) = pred(a1) ∧ ... pred(an) ∧ pred(b1) ∧ ... ∧ pred(bn)как
(pred(a1) ∧ ... pred(an)) ∧ (pred(b1) ∧ ... ∧ pred(bn)) = all(a, pred) ∧ all(b, pred)Или, иными словами и в синтаксисе Rust, если
x и
y — итераторы, то логично ожидать, что
x.chain(y).all(p) вернёт тот же результат, что и
x.all(p) && y.all(p).
Это свойство должно работать для любых последовательностей, включая пустые. С другой стороны, любую последовательность можно представить, как конкатенацию этой же последовательности с пустой. Или, в синтаксисе Rust, с поправкой на типы
x и
x.chain(iter::empty()) ведут себя одинаково. Подставив это в свойство выше, мы получаем, что
x.all(p) && iter::empty().all(p),
x.chain(iter::empty()).all(p) и
x.all(p) должны возвращать один и тот же результат. Для произвольного итератора
x это возможно только в том случае, если
iter::empty().all(p) возвращает значений, нейтральное для коньюкции, то есть
true. Иными словами,
Iterator::all должен возвращать
true на пустом итераторе, ч. и т. д.
Аналогичные соображения показывают, почему
Iterator::any должен возвращать
false.