Part 5. Iterating manually (10 points)

Similar to the previous part, you will implement a function and some unit tests.

Your task

Write a function that iterates over the elements in its argument and adds them all and returns the sum.

fn main() {
fn manual_sum(data: &[i32]) -> i32 {
    let mut data_iter = data.iter();
    todo!("Implement me")

The catch is that for this task, you may not use a for loop. Instead, you’ll need to work with the iterator returned by data.iter() directly. Iterators in Rust work similarly to iterators in Java. To implement this as a Java method using iterators rather than a for loop we might use something like this.

int manualSum(ArrayList<Integer> data) {
    int sum = 0;
    Iterator<Integer> iter = data.iterator();
    while (iter.hasNext()) {
        sum +=;
    return sum;

Iterators in Rust don’t have separate has_next() and next() methods. Instead, there’s just a single next() method that returns an Option<T>. Every Option is either None or Some(blah) for some value blah. Here’s a simple example of using an Option.

fn main() {
let x: Option<i32> = Some(10);
assert_eq!(x.unwrap(), 10);

let y: Option<i32> = None;

We can use is_some() or is_none() to determine if an Option is a Some or a None. If we have a Some, then we can unwrap it by calling unwrap() which returns the data. If we try calling unwrap() on None, we’ll get a runtime error.

Write some unit tests. Make sure you cover all of the following cases.

  1. Empty data (where the sum should be 0);
  2. Single-element vectors; and
  3. Vectors with multiple elements.

Implement manual_sum by calling next() on data_iter repeatedly until the result is None. Unwrap all of the other values and sum them up.


You’ll probably want a loop like this.

loop {
    // XXX: Get the next element from the iterator
    if /* the element is None */ {
      return sum;
    // XXX: Unwrap and add the value to the sum.