I was reading a useful post at WRI blog on improving speed of code, and I need help in understanding this one.
Compare these speeds
Timing[
tbl = Table[i + j, {i, 1, 1000}, {j, 1, 1000}];
]
{0.031, Null}
and
Timing[
a = 1000;
tbl = Table[i + j, {i, 1, a}, {j, 1, a}];
]
{0.422, Null}
So it is much faster when putting the actual value for the limit inside the table itself vs outside. The explanation for this, which I am sure it is correct, but I need help in understanding, is that Table is compiled if its limit are numeric vs. not, this is because its Attributes is HoldAll.
But my question is: How would the above actually work, because the limits to Table must, at one point, become numeric anyway? I can't write
Clear[a]
tbl = Table[i + j, {i, 1, a}, {j, 1, a}]
The above gives an error.
So, for me, writing a=1000 outside Table vs. inside, should have made no difference, since without a having a numerical value, Table[] can't do anything. So the replacing of a by the number 1000 must occur at one point of time by evaluator before Table[] can do anything useful, would it not?
In other words, what Table should see, eventually, is {i, 1, 1000}, {j, 1, 1000} in both cases.
So, the way I thought this would happen is this:
- Evaluator replaces
aby 1000 in the arguments of table - Evaluator calls
Tablewith the result, which is now all numeric. - Table Compiles, and runs faster now.
But what seems to happen is something else. (due to HoldAll ?)
- Table takes its arguments, a