instance method
Enumerable#sum
() -> (Elem | ::Integer)
[T] () { (Elem arg0) -> T } -> (::Integer | T)
[T] (?T arg0) -> (Elem | T)
[U] (?U arg0) { (Elem arg0) -> U } -> U
sum(initial_value = 0) → number
sum(initial_value = 0) {|element| ... } → object
enum.c
View on GitHub ↗
static VALUE
enum_sum(int argc, VALUE* argv, VALUE obj)
{
struct enum_sum_memo memo;
VALUE beg, end;
int excl;
memo.v = (rb_check_arity(argc, 0, 1) == 0) ? LONG2FIX(0) : argv[0];
memo.block_given = rb_block_given_p();
memo.n = 0;
memo.r = Qundef;
if ((memo.float_value = RB_FLOAT_TYPE_P(memo.v))) {
memo.f = RFLOAT_VALUE(memo.v);
memo.c = 0.0;
}
else {
memo.f = 0.0;
memo.c = 0.0;
}
if (RTEST(rb_range_values(obj, &beg, &end, &excl))) {
if (!memo.block_given && !memo.float_value &&
(FIXNUM_P(beg) || RB_BIGNUM_TYPE_P(beg)) &&
(FIXNUM_P(end) || RB_BIGNUM_TYPE_P(end))) {
return int_range_sum(beg, end, excl, memo.v);
}
}
if (RB_TYPE_P(obj, T_HASH) &&
rb_method_basic_definition_p(CLASS_OF(obj), id_each))
hash_sum(obj, &memo);
else
rb_block_call(obj, id_each, 0, 0, enum_sum_i, (VALUE)&memo);
if (memo.float_value) {
return DBL2NUM(memo.f + memo.c);
}
else {
if (memo.n != 0)
memo.v = rb_fix_plus(LONG2FIX(memo.n), memo.v);
if (!UNDEF_P(memo.r)) {
memo.v = rb_rational_plus(memo.r, memo.v);
}
return memo.v;
}
}
With no block given, returns the sum of initial_value and the elements:
Example
(1..100).sum # => 5050 (1..100).sum(1) # => 5051 ('a'..'d').sum('foo') # => "fooabcd"
Generally, the sum is computed using methods + and each; for performance optimizations, those methods may not be used, and so any redefinition of those methods may not have effect here.
One such optimization: When possible, computes using Gauss’s summation formula n(n+1)/2:
Example
100 * (100 + 1) / 2 # => 5050
With a block given, calls the block with each element; returns the sum of initial_value and the block return values:
Example
(1..4).sum {|i| i*i } # => 30 (1..4).sum(100) {|i| i*i } # => 130 h = {a: 0, b: 1, c: 2, d: 3, e: 4, f: 5} h.sum {|key, value| value.odd? ? value : 0 } # => 9 ('a'..'f').sum('x') {|c| c < 'd' ? c : '' } # => "xabc"