I think I found out how it works in some old literature, in particular David Wagner's book which references David Withoff's tutorial. Withoff states that the system keeps track of the time of last evaluation of normal expressions, and mentions that normal expressions are not evaluated again unless a part of them changes. I think that the creation of normal expression itself counts as the "first evaluation". I did some tests with constant array.The question was made with RandomReal but the point was really about unnecessary evaluation of large normal expressions and the output of RandomReal is an atom(I discovered that latter). I wanted something whose output would be a large normal expression.
The code is:
test = Table[ConstantArray[a, 5*i*10^3]; // Timing, {i, 1, 10^5, 1000}];
test = Drop[test, None, -1];
test2 = Table[5*i*10^3, {i, 1, 10^5, 1000}];
test = Riffle[test2, Flatten@test] // Partition[#, 2] &;
test = MapIndexed[Prepend[#1, 10^6*Max@#2] &, test, {1}];
ListPlot[test]
I calculated a lot of constant arrays with an undefined symbol "a" (ensuring that the result is a normal expression and that its reevaluation would be a waste of time), and them I plot the time to calculate them against their lengths.
The scaling seems linear, if it were the case that the kernel was attempting to evaluate the arrays I would expect a quadratic scaling (horizontal axis is array length). Naturally, I am assuming that the process of creating arrays with the same components has a linear scaling, if someone knows this to be false please let me know. To me this is evidence that the kernel is not trying to evaluate the normal expression once it gets it, and I think the reason is related to Whitoff's statement. I am conjecturing that the creation of the normal expression itself already counts as an "evaluation".
Michael E2 suggested that the reason could be related to a "Valid" flag, associated with System`Private`SetValid
. It is hard to say for certain that this is not the case because there is no documentation on it. However, I tried to test applying System`Private`ValidQ
in RandomReal, ConstantArray and their outputs and it gives False. So it seems unlikely for me.
Goofy gave a nice application of TraceScan to investigate the question and things get weird here. Goofy's application to a simple ConstantArray[a,10]
suggest that the kernel attempts to reevaluate the the output of ConstantArray, because there are 10 rules of the type a->a
, apart of a List->List
. However, is hard for me to believe that the reevaluation of vectors with about 10^6 elements and more would not introduce a x^2 behavior in the plot. So maybe TraceScan affects somehow what happens, I am not sure because I am not quite familiar with it.