ExamplesBy LevelBy TopicLearning Paths
093 Intermediate

093 — Windows and Chunks

Functional Programming

Tutorial

The Problem

Use Rust's slice methods .windows(n) and .chunks(n) to create overlapping and non-overlapping subslice iterators. Demonstrate that windows slides one element at a time (producing len - n + 1 windows) while chunks partitions without overlap (last chunk may be shorter). Compare with OCaml's manual recursive implementations.

🎯 Learning Outcomes

  • • Apply slice.windows(n) for overlapping n-element views
  • • Apply slice.chunks(n) for non-overlapping n-element partitions
  • • Understand that both return iterators of &[T] — zero-copy subslice references
  • • Use chunks_exact(n) when trailing partial chunks should be excluded
  • • Map Rust's built-in slice methods to OCaml's recursive list splitting
  • • Recognise common uses: sliding averages (windows), batch processing (chunks)
  • Code Example

    #![allow(clippy::all)]
    // 093: Windows and Chunks
    
    #[cfg(test)]
    mod tests {
        #[test]
        fn test_windows() {
            let v = vec![1, 2, 3, 4, 5];
            let w: Vec<&[i32]> = v.windows(3).collect();
            assert_eq!(w, vec![&[1, 2, 3][..], &[2, 3, 4][..], &[3, 4, 5][..]]);
        }
    
        #[test]
        fn test_windows_2() {
            let v = vec![1, 2, 3];
            let w: Vec<&[i32]> = v.windows(2).collect();
            assert_eq!(w, vec![&[1, 2][..], &[2, 3][..]]);
        }
    
        #[test]
        fn test_chunks() {
            let v = vec![1, 2, 3, 4, 5];
            let c: Vec<&[i32]> = v.chunks(2).collect();
            assert_eq!(c, vec![&[1, 2][..], &[3, 4][..], &[5][..]]);
        }
    
        #[test]
        fn test_chunks_exact() {
            let v = vec![1, 2, 3, 4, 5, 6];
            let c: Vec<&[i32]> = v.chunks(3).collect();
            assert_eq!(c, vec![&[1, 2, 3][..], &[4, 5, 6][..]]);
        }
    }

    Key Differences

    AspectRustOCaml
    Windowsslice.windows(n) built-inManual recursive function
    Chunksslice.chunks(n) built-inManual recursive function
    Element type&[T] (borrowed subslice)'a list (new list)
    AllocationZero-copyAllocates sublists
    Exact chunkschunks_exact(n)Manual length check
    String windowss.as_bytes().windows(n)Substring extraction

    windows is particularly useful for sliding window algorithms: computing moving averages, detecting runs, or finding maximum subarray sums. chunks is useful for batch processing: splitting work across threads or formatting data in fixed-size blocks.

    OCaml Approach

    OCaml has no built-in windows/chunks on lists. The recursive windows n lst takes a prefix of length n, adds it to the accumulator, and recurses on the tail. chunks n lst groups elements into sublists of size n. Both use List.rev and manual counting — more verbose than Rust's built-in methods. Array operations (Array.sub) would be closer to Rust's approach.

    Full Source

    #![allow(clippy::all)]
    // 093: Windows and Chunks
    
    #[cfg(test)]
    mod tests {
        #[test]
        fn test_windows() {
            let v = vec![1, 2, 3, 4, 5];
            let w: Vec<&[i32]> = v.windows(3).collect();
            assert_eq!(w, vec![&[1, 2, 3][..], &[2, 3, 4][..], &[3, 4, 5][..]]);
        }
    
        #[test]
        fn test_windows_2() {
            let v = vec![1, 2, 3];
            let w: Vec<&[i32]> = v.windows(2).collect();
            assert_eq!(w, vec![&[1, 2][..], &[2, 3][..]]);
        }
    
        #[test]
        fn test_chunks() {
            let v = vec![1, 2, 3, 4, 5];
            let c: Vec<&[i32]> = v.chunks(2).collect();
            assert_eq!(c, vec![&[1, 2][..], &[3, 4][..], &[5][..]]);
        }
    
        #[test]
        fn test_chunks_exact() {
            let v = vec![1, 2, 3, 4, 5, 6];
            let c: Vec<&[i32]> = v.chunks(3).collect();
            assert_eq!(c, vec![&[1, 2, 3][..], &[4, 5, 6][..]]);
        }
    }
    ✓ Tests Rust test suite
    #[cfg(test)]
    mod tests {
        #[test]
        fn test_windows() {
            let v = vec![1, 2, 3, 4, 5];
            let w: Vec<&[i32]> = v.windows(3).collect();
            assert_eq!(w, vec![&[1, 2, 3][..], &[2, 3, 4][..], &[3, 4, 5][..]]);
        }
    
        #[test]
        fn test_windows_2() {
            let v = vec![1, 2, 3];
            let w: Vec<&[i32]> = v.windows(2).collect();
            assert_eq!(w, vec![&[1, 2][..], &[2, 3][..]]);
        }
    
        #[test]
        fn test_chunks() {
            let v = vec![1, 2, 3, 4, 5];
            let c: Vec<&[i32]> = v.chunks(2).collect();
            assert_eq!(c, vec![&[1, 2][..], &[3, 4][..], &[5][..]]);
        }
    
        #[test]
        fn test_chunks_exact() {
            let v = vec![1, 2, 3, 4, 5, 6];
            let c: Vec<&[i32]> = v.chunks(3).collect();
            assert_eq!(c, vec![&[1, 2, 3][..], &[4, 5, 6][..]]);
        }
    }

    Deep Comparison

    Core Insight

    Windows overlap, chunks don't — both view contiguous data without copying

    OCaml Approach

  • • See example.ml for implementation
  • Rust Approach

  • • See example.rs for implementation
  • Comparison Table

    FeatureOCamlRust
    Seeexample.mlexample.rs

    Exercises

  • Compute a 3-element moving average of a Vec<f64> using windows(3).
  • Use windows(2) to count adjacent pairs where the second element is greater than the first (number of increases).
  • Implement batch_process<T, F>(items: &[T], batch_size: usize, f: F) using chunks to process items in groups.
  • Use v.windows(2) to implement is_sorted(v: &[i32]) -> bool.
  • In OCaml, implement windows_seq n lst using Seq for laziness — producing windows on demand without materialising all at once.
  • Open Source Repos