Constructing expressions using Sum vs Array[… Plus] vs Plus@@Table[…]

For constructing a sum of terms which are symbolic, I noticed that in addition to

Sum[f[i],{i,1,10}]

(* f + f + f + f + f + f + f + f + f + f *)

I can also do

Array[f,10,1,Plus]

(* f + f + f + f + f + f + f + f + f + f *)

or even Plus@@Table[f[i],{i,1,10}] or Total[Table[f[i],{i,1,10}]].

While it is not a huge surprise I'm able to achieve the same result using different functions in Mathematica, I'm wondering if there are specific use cases which prefers one form over another for the construction of a sum of symbolic terms. Right now all I can think of for Array is that there the local iterator i is not needed. But performance/memory-wise, is there something else I should be aware of?

• Michael Trott in Programming (pp 707 - 710) argues that as Table has the attribute HoldAll it computes its argument for every call, whereas Array "to the extent possible" computes its argument only at the beginning. This may lead to differences in behaviour as well as speed. Compare (example given by MT) a = 0; Table[a = a + 1; ToExpression[StringJoin["a" <> ToString[a]]][i, j], {i, 3}, {j, 3}] to a = 0; Array[a = a + 1; ToExpression[StringJoin["a" <> ToString[a]]], {3, 3}]. Old SO question – user1066 Jul 1 '18 at 7:30

This is something that you could have tested yourself, quite easily. I sugest the use of RepeatedTiming for more reliable measurements.

BarChart[
{
First@RepeatedTiming[
Sum[f[i], {i, 1, 100}]
],
First@RepeatedTiming[
Array[f, 100, 1, Plus]
],
First@RepeatedTiming[
Total@Table[f[i], {i, 1, 100}]
],
First@RepeatedTiming[
Plus @@ Table[f[i], {i, 1, 100}]
],
First@RepeatedTiming[
Plus @@ (f /@ Range)
],
First@RepeatedTiming[
Total[f /@ Range]
]
} 10^6
, ChartLabels -> {
"Sum",
"Array[_,Plus]",
"Total@Table",
"Plus@@Table",
"Plus@@Range",
"Total-Range"
}
, PlotTheme -> "Scientific"
, AspectRatio -> 1/2
, FrameLabel -> {"Method", "Time \[Mu]s"}
, ImageSize -> 600
] • Ok, that's interesting data. It seems to support the use of Array in the simplest case of f. Having this result can be useful to others. I'm also looking answers from seasoned/experienced programmers as well. – QuantumDot Jun 30 '18 at 20:35
• @QuantumDot it will also depend on the auto-compilation and whether your arrays and things are packed, although I still expect Array to do best there. Also of interest might be a Fold[#+f[#2]&, ...] type thing, although if all is as I expect that will be slowest. – b3m2a1 Jul 1 '18 at 5:45
• f /@ Range is more efficient than Table[f[i], {i, 1, 100}] with either Total or Plus – Bob Hanlon Jul 1 '18 at 14:27
• @BobHanlon, OK, I included that in the comparison. – rhermans Jul 1 '18 at 14:39

Sum isn't really for constructing expressions: it's primarily for finding an analytic formula that represents a sum. It's mostly useful when bounds are unknown or infinite:

Sum[1/2^i, {i, 1, n}]
(* 2^-n (-1 + 2^n) *)

Mere expression construction can't do this.