Search code examples
rust

How can I sum a range of numbers in Rust?


I want to write a function to sum the numbers from zero to n. (Ideally, this would be generic over all numbers, but I will settle for i32).

mod squares {

    pub fn sum_from_zero( n: i32) -> i32 {
        [0 .. n].fold(0, |a, b| a + b)
    }
}

#[test]
fn test_sum_from_zero() {
    assert_eq!(15, squares::sum_from_zero(5));
}

I get the following compiler error:

src/lib.rs:5:18: 5:22 error: no method named `fold` found for type `[std::ops::Range<i32>; 1]` in the current scope
src/lib.rs:5         [0 .. n].fold(0, |a, b| a + b)
                              ^~~~
src/lib.rs:5:18: 5:22 note: the method `fold` exists but the following trait bounds were not satisfied: `[std::ops::Range<i32>; 1] : std::iter::Iterator`, `[std::ops::Range<i32>] : std::iter::Iterator`

I've also tried this with sum():

mod squares {

    pub fn sum_from_zero( n: i32) -> i32 {
        [0 .. n].sum()
    }
}

#[test]
fn test_sum_from_zero() {
    assert_eq!(15, squares::sum_from_zero(5));
}

And got the following compiler error:

src/lib.rs:5:18: 5:21 error: no method named `sum` found for type `[std::ops::Range<i32>; 1]` in the current scope
src/lib.rs:5         [0 .. n].sum()
                              ^~~
src/lib.rs:5:18: 5:21 note: the method `sum` exists but the following trait bounds were not satisfied: `[std::ops::Range<i32>; 1] : std::iter::Iterator`, `[std::ops::Range<i32>] : std::iter::Iterator`
src/lib.rs:5:18: 5:21 error: no method named `sum` found for type `[std::ops::Range<i32>; 1]` in the current scope
src/lib.rs:5         [0 .. n].sum()
                              ^~~
src/lib.rs:5:18: 5:21 note: the method `sum` exists but the following trait bounds were not satisfied: `[std::ops::Range<i32>; 1] : std::iter::Iterator`, `[std::ops::Range<i32>] : std::iter::Iterator`

Do I have to declare explicit bounds/traits?


Solution

  • The problem is that you are creating an array of ranges (square brackets) but you just wanted the range (on which fold is defined).

    Another thing is that range syntax (..) is only inclusive of the lower bound. It's exclusive of the upper bound so you have to iterate up to n+1 to get the desired result.

    mod squares {
    
        pub fn sum_from_zero( n: i32) -> i32 {
            (0 .. n+1).fold(0, |a, b| a + b)
        }
    }
    
    #[test]
    fn test_sum_from_zero() {
        assert_eq!(15, squares::sum_from_zero(5));
    }