The mathematica documentation on Evaluate at possible issues says:
Evaluate works only on the first
level, directly inside a held function
Why does Mathematica have this limitation? So if I have an expression with more than one level take this simplified example:
Hold[Plus[Plus[2, 2], 2]]]
Now suppose I want to see what the answer is to the the second Plus, without evaluating anything on levels below it. I’ve tried different things such as:
In[290]:= Hold[Plus[Evaluate[Plus[2, 2]], 2]]
Out[290]= Hold[Evaluate[2+2]+2]
In[287]:= Hold[Plus[ReleaseHold[Hold[Plus[2, 2]]], 2]]
Out[287]= Hold[ReleaseHold[Hold[2+2]]+2]
The first Hold keeps everything unevaluated at and beyond the first level in this case.
The goal is to control evaluation of an expression at each stage from the most inner nested function to the outer one using successive Hold, ReleaseHold and Evaluate functions to achieve that. I know I could use trace to see what happens beyond level one in an expression but that is different and sometimes complex to read with longer expressions.
It seems like the only way is to extract and totally dismantle the expression into lists using Extract, Part or Level; evaluate part of the expression that I want; then reconstruct and re-map the expression back together for each stage. Are there any other approaches or functions for achieving this I could consider?
Edit: This might be a better example to look at the approach of releasing the first hold. With the expression:
Hold[Plus[Plus[2, Plus[2,2]], 2]]]
If you release the first hold and place a hold on a higher level in a expression at the third Plus, to look like this:
in = Plus[Plus[2, Hold[Plus[2,2]]], 2]]]
out = Hold[2+2]+4
You find that Mathematica will evaluate lower levels in the background when you really want it to wait.
I can’t give the exact reason why
Evaluate“works only on the first level, directly inside a held function” but I suspect it’s partly efficiency, in that it would be slow if the evaluator had to scan the complete expression tree of held arguments passed to any function with aHold*attribute for nestedEvaluateexpressions and evaluate them, and then recurse and look forEvaluatesubexpressions in what it just evaluated, all while keeping the rest of the expression unevaluated, especially when this might not always be what you want to happen anyway.Doing what you want is pretty easy using a combination of
ExtractandReplacePartthough:This lets us illustrate another reason why it might not make sense for
Evaluateto work at any level in an expression passed as an argument to a function with aHold*attribute, considering the following expression involvingi:Note that the value of
jwould have been4if we had evaluated the first part of that expression before thePlus, but the results are different since we are only doing partial evaluation, andi=2had not been evaluated when we evaluated the subexpression settingj. Sometimes, this may be what you want to happen, but often it is very likely not.Keep in mind that even
Evaluatein the first level can be defeated by a function that has the attributeHoldAllCompleteor by usingHoldComplete:…versus:
Finally, the output of
Tracecan be a little dense, but you can filter out what you want by using patterns or symbols of interest in the second argument:HTH!