265: Conditional Skipping with skip_while()
Functional Programming
Tutorial
The Problem
Data streams often begin with a preamble, header, or leading values that should be ignored before processing begins. Log files start with timestamps; CSV files may have metadata rows; sorted lists may have leading zeros. The skip_while() adapter solves this by discarding elements from the front of an iterator until the predicate first returns false, then yielding all remaining elements unconditionally — including any that would again match the original predicate.
🎯 Learning Outcomes
skip_while(pred) discards elements until predicate first fails, then yields everything afterskip_while() from filter(): later matching elements are still includedskip_while() to skip headers, leading whitespace, or sentinel valuesskip_while() with take_while() to extract a middle segment of a sequenceCode Example
#![allow(clippy::all)]
//! 265. Conditional skipping with skip_while()
//!
//! `skip_while(pred)` discards elements until predicate first returns false, then yields all remaining.
#[cfg(test)]
mod tests {
#[test]
fn test_skip_while_basic() {
let result: Vec<i32> = [1, 2, 3, 4, 5]
.iter()
.copied()
.skip_while(|&x| x < 3)
.collect();
assert_eq!(result, vec![3, 4, 5]);
}
#[test]
fn test_skip_while_includes_later_matches() {
let result: Vec<i32> = [0i32, 0, 1, 0]
.iter()
.copied()
.skip_while(|&x| x == 0)
.collect();
assert_eq!(result, vec![1, 0]);
}
#[test]
fn test_skip_while_all() {
let result: Vec<i32> = [1, 2, 3].iter().copied().skip_while(|&x| x < 10).collect();
assert!(result.is_empty());
}
#[test]
fn test_skip_while_none() {
let result: Vec<i32> = [1, 2, 3].iter().copied().skip_while(|&x| x > 10).collect();
assert_eq!(result, vec![1, 2, 3]);
}
}Key Differences
skip_while yield everything after the first false, including later matches — this is by design for ordered prefix stripping.Iterator; OCaml's standard List module lacks it (third-party Base provides List.drop_while).take_while**: Together they split a sequence: take_while(p) takes the prefix, skip_while(p) takes the suffix.take_while, it is stateful and not equivalent to a filter — order matters.OCaml Approach
OCaml's List.drop_while (in Base/Core) or a recursive equivalent serves this role:
let rec skip_while pred = function
| [] -> []
| x :: xs -> if pred x then skip_while pred xs else x :: xs
Seq.drop_while provides the lazy equivalent for sequences, identical semantically to Rust's skip_while.
Full Source
#![allow(clippy::all)]
//! 265. Conditional skipping with skip_while()
//!
//! `skip_while(pred)` discards elements until predicate first returns false, then yields all remaining.
#[cfg(test)]
mod tests {
#[test]
fn test_skip_while_basic() {
let result: Vec<i32> = [1, 2, 3, 4, 5]
.iter()
.copied()
.skip_while(|&x| x < 3)
.collect();
assert_eq!(result, vec![3, 4, 5]);
}
#[test]
fn test_skip_while_includes_later_matches() {
let result: Vec<i32> = [0i32, 0, 1, 0]
.iter()
.copied()
.skip_while(|&x| x == 0)
.collect();
assert_eq!(result, vec![1, 0]);
}
#[test]
fn test_skip_while_all() {
let result: Vec<i32> = [1, 2, 3].iter().copied().skip_while(|&x| x < 10).collect();
assert!(result.is_empty());
}
#[test]
fn test_skip_while_none() {
let result: Vec<i32> = [1, 2, 3].iter().copied().skip_while(|&x| x > 10).collect();
assert_eq!(result, vec![1, 2, 3]);
}
}
✓ Tests
Rust test suite
#[cfg(test)]
mod tests {
#[test]
fn test_skip_while_basic() {
let result: Vec<i32> = [1, 2, 3, 4, 5]
.iter()
.copied()
.skip_while(|&x| x < 3)
.collect();
assert_eq!(result, vec![3, 4, 5]);
}
#[test]
fn test_skip_while_includes_later_matches() {
let result: Vec<i32> = [0i32, 0, 1, 0]
.iter()
.copied()
.skip_while(|&x| x == 0)
.collect();
assert_eq!(result, vec![1, 0]);
}
#[test]
fn test_skip_while_all() {
let result: Vec<i32> = [1, 2, 3].iter().copied().skip_while(|&x| x < 10).collect();
assert!(result.is_empty());
}
#[test]
fn test_skip_while_none() {
let result: Vec<i32> = [1, 2, 3].iter().copied().skip_while(|&x| x > 10).collect();
assert_eq!(result, vec![1, 2, 3]);
}
}
Exercises
skip_while(|c| c.is_whitespace()).# (comment lines at the top).skip_while() and take_while() to extract only the elements between two sentinel values in a sequence.