Reputation: 2833
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?
Upvotes: 11
Views: 12471
Reputation: 454
All of the answers ignore the fact, that the OP wants to sum i32
, not u32
from 0 to n. This implies that there may also be negative sums involved (0 + -1 + -2 + ... + n). Hence, I propose:
fn summation(n: i32) -> i32 {
if n < 0 {
(n..0).sum()
} else {
(0..=n).sum()
}
}
Upvotes: 0
Reputation: 21
I recommend to use that the sum you're looking for is equal to n*(n+1)/2; assuming that there is no reason against using that, because you did not mention any in your question.
Upvotes: 2
Reputation: 106
Other people have given valid answers, but I assume the following is the simplest way to do it.
fn summation(n: i32) -> i32 {
(0..=n).sum()
}
#[cfg(test)]
mod tests {
use super::summation;
#[test]
fn basic_tests() {
assert_eq!(summation(1), 1);
assert_eq!(summation(8), 36);
assert_eq!(summation(22), 253);
assert_eq!(summation(100), 5050);
assert_eq!(summation(213), 22791);
}
}
Upvotes: 3
Reputation: 11
You can use the Iterator trait, which includes the sum method, to sum a range of numbers. Here's an example implementation:
mod squares {
pub fn sum_from_zero(n: i32) -> i32 {
(0..=n).into_iter().sum()
}
}
Upvotes: 1
Reputation: 21505
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));
}
Upvotes: 18