ExamplesBy LevelBy TopicLearning Paths
919 Intermediate

919-iterator-any-all — Iterator any and all

Functional Programming

Tutorial

The Problem

Existential and universal quantification over sequences — "does any element satisfy X?" and "do all elements satisfy X?" — are fundamental logic operations. In formal logic, ∃ (exists) and ∀ (for all). In SQL, EXISTS and NOT EXISTS. In Haskell, any and all. In OCaml, List.exists and List.for_all. Rust's Iterator::any() and Iterator::all() short-circuit: any stops at the first true, all stops at the first false. This makes them efficient even on large sequences and safe on infinite iterators (as long as the condition is eventually met).

🎯 Learning Outcomes

  • • Use .any(pred) for existential checking (∃ — short-circuits on first true)
  • • Use .all(pred) for universal checking (∀ — short-circuits on first false)
  • • Understand vacuous truth: .all() on an empty iterator returns true
  • • Understand vacuous false: .any() on an empty iterator returns false
  • • Compare with OCaml's List.exists and List.for_all
  • Code Example

    #![allow(clippy::all)]
    //! 280. Existential checks: any() and all()
    //!
    //! `any(pred)` is ∃, `all(pred)` is ∀ — both short-circuit.
    
    #[cfg(test)]
    mod tests {
        #[test]
        fn test_any_true() {
            assert!([1i32, 2, 3].iter().any(|&x| x == 2));
        }
    
        #[test]
        fn test_any_false() {
            assert!(![1i32, 2, 3].iter().any(|&x| x == 9));
        }
    
        #[test]
        fn test_all_true() {
            assert!([2i32, 4, 6].iter().all(|&x| x % 2 == 0));
        }
    
        #[test]
        fn test_all_false() {
            assert!(![1i32, 2, 3].iter().all(|&x| x % 2 == 0));
        }
    
        #[test]
        fn test_vacuous_truth() {
            let empty: Vec<i32> = vec![];
            assert!(empty.iter().all(|_| false)); // vacuously true
            assert!(!empty.iter().any(|_| true)); // no elements
        }
    }

    Key Differences

  • Identical semantics: any/all in Rust and exists/for_all in OCaml have exactly the same short-circuit behavior and vacuous truth/false rules.
  • Syntax: Rust uses method syntax iter.any(pred); OCaml uses function syntax List.exists pred xs.
  • Short-circuit on infinite: Rust (0..).any(|x| x > 100) terminates; (0..).all(|x| x < 100) would loop forever — same constraint applies to OCaml Seq.
  • Negation: !any(pred) = all(!pred) by De Morgan's law — both languages implement this complementary relationship.
  • OCaml Approach

    List.exists: ('a -> bool) -> 'a list -> bool — equivalent to any. List.for_all: ('a -> bool) -> 'a list -> bool — equivalent to all. Both short-circuit. Vacuous behavior: List.for_all pred [] = true; List.exists pred [] = false. For sequences: Seq.exists and Seq.for_all (since 4.14). The semantics are identical to Rust's; the difference is method vs function call syntax.

    Full Source

    #![allow(clippy::all)]
    //! 280. Existential checks: any() and all()
    //!
    //! `any(pred)` is ∃, `all(pred)` is ∀ — both short-circuit.
    
    #[cfg(test)]
    mod tests {
        #[test]
        fn test_any_true() {
            assert!([1i32, 2, 3].iter().any(|&x| x == 2));
        }
    
        #[test]
        fn test_any_false() {
            assert!(![1i32, 2, 3].iter().any(|&x| x == 9));
        }
    
        #[test]
        fn test_all_true() {
            assert!([2i32, 4, 6].iter().all(|&x| x % 2 == 0));
        }
    
        #[test]
        fn test_all_false() {
            assert!(![1i32, 2, 3].iter().all(|&x| x % 2 == 0));
        }
    
        #[test]
        fn test_vacuous_truth() {
            let empty: Vec<i32> = vec![];
            assert!(empty.iter().all(|_| false)); // vacuously true
            assert!(!empty.iter().any(|_| true)); // no elements
        }
    }
    ✓ Tests Rust test suite
    #[cfg(test)]
    mod tests {
        #[test]
        fn test_any_true() {
            assert!([1i32, 2, 3].iter().any(|&x| x == 2));
        }
    
        #[test]
        fn test_any_false() {
            assert!(![1i32, 2, 3].iter().any(|&x| x == 9));
        }
    
        #[test]
        fn test_all_true() {
            assert!([2i32, 4, 6].iter().all(|&x| x % 2 == 0));
        }
    
        #[test]
        fn test_all_false() {
            assert!(![1i32, 2, 3].iter().all(|&x| x % 2 == 0));
        }
    
        #[test]
        fn test_vacuous_truth() {
            let empty: Vec<i32> = vec![];
            assert!(empty.iter().all(|_| false)); // vacuously true
            assert!(!empty.iter().any(|_| true)); // no elements
        }
    }

    Exercises

  • Use .any() and .all() to implement is_valid_sudoku_row(row: &[u8]) -> bool that checks for values 1-9 with no duplicates.
  • Write has_balanced_parens(s: &str) -> bool using .scan() on chars and .all() on the running count.
  • Implement exactly_one<T>(data: &[T], pred: impl Fn(&T) -> bool) -> bool that returns true if exactly one element satisfies the predicate.
  • Open Source Repos