6
$\begingroup$

Bug introduced in 8.0.4 or earlier and persisting through 12.0 or later


Check this example:

Attributes[Unevaluated]
(*{HoldAllComplete, Protected}*)
FullForm[Unevaluated[{{5 + 6}, {7 + 8}}]]
(*Unevaluated[List[List[Plus[5, 6]], List[Plus[7, 8]]]]*)

now:

TreeForm[Unevaluated[{{5 + 6}, {7 + 8}}]]

enter image description here

expr = Unevaluated[{{5 + 6}, {7 + 8}}]

(*{{11}, {15}}*)

Note here the result is like Unevaluated is not applied at all.

It looks like (according to the documentation also) that Unevaluated uses its Attributes ONLY once.

When compared with HoldComplete, which has same Attributes, the results are different and as expected.

in the case of HoldComplete:

FullForm[HoldComplete[{{5 + 6}, {7 + 8}}]]
(*HoldComplete[List[List[Plus[5, 6]], List[Plus[7, 8]]]]*)
TreeForm[HoldComplete[{{5 + 6}, {7 + 8}}]]

enter image description here

It is clear that the TreeForm does not represent the FullForm when using Unevaluated and works perfectly in the case of HoldComplete.

How does that happen with Unevaluated?

$\endgroup$
8
  • $\begingroup$ @kuba, you can see that the TreeFrom does not represent the FullForm. the TreeForm is like Unevaluated is not applied at all. Furthermore the result of expr = Unevaluated[{{5 + 6}, {7 + 8}}] is also like Unevaluated is not applied. I will try to edit the equation now. $\endgroup$ Nov 26, 2014 at 9:08
  • $\begingroup$ Relevant StackOverflow thread: "Why does TreeForm[Unevaluated[4^5]] evaluate the 4^5?" $\endgroup$ Nov 28, 2014 at 21:07
  • $\begingroup$ Related: 1, 2. $\endgroup$ Nov 28, 2014 at 21:12
  • $\begingroup$ I'd say Unevaluated is underdocumented. But I do not see a bug here. Internals of function implementations are allowed to strip Unevaluated and presumably TreeForm is doing just that. $\endgroup$ Mar 6, 2017 at 15:22
  • $\begingroup$ @DanielLichtblau "Internals of function implementations are allowed to strip Unevaluated" - Isn't this called evaluation leak? $\endgroup$ Aug 22, 2019 at 5:12

1 Answer 1

7
$\begingroup$

What you observe is a bug (evaluation leak) inside of TreeForm. In particular, observe this:

TreeForm[Unevaluated[Print[5 + 6]]]
11
11

As you see, Print is evaluated twice inside of the TreeForm code. It is apparent bug and I suggest you to report it to technical support.

Note that in Mathematica 5.2 TreeForm doesn't have the evaluation leak:

enter image description here

There is no leak in the terminal interface in newer versions too:

enter image description here

From this comes a workaround - just wrap TreeForm with OutputForm:

TreeForm[Unevaluated[Print[5 + 6]]] // OutputForm

enter image description here

Note that this behavior is still not completely in accord with the Documentation for Unevaluated: since TreeForm doesn't have the HoldAllComplete attribute, the Unevaluated wrapper should be stripped off on the first stage of the evaluation process temporarily setting this attribute to TreeForm (refs: "Details" section on ref/Unevaluated and the fourth bullet point under the "The Standard Evaluation Sequence").

Also TreeForm displays strings without quotes by default what makes it difficult to separate them from Symbols. But on the base of this feature we can easily make the correct treeForm by converting all the Symbols and Strings into InputForm strings:

treeForm[expr_, opts___] := 
 TreeForm[Unevaluated[
    expr] /. {s : (_Symbol | _String) :> ToString[Unevaluated[s], InputForm]}, opts]

treeForm[Unevaluated[Print[5 + 6 + "string"]], ImageSize -> 300, PlotRangePadding -> .4]

screenshot

But it still requires additional work to make it working correctly with Image and probably some other atomic objects.

$\endgroup$
7
  • $\begingroup$ Alexey Pokov, sorry for late reply. I think the problem is with Unevaluated not TreeForm. check expr = Unevaluated[{{5 + 6}, {7 + 8}}] you will see that this will evaluate Unevaluated argument. $\endgroup$ Dec 2, 2014 at 18:11
  • $\begingroup$ The expected behavior of TreeForm should be as in this example: treeForm@Unevaluated[{{5 + 6}, {7 + 8}}] (it is the documented behavior). Your example is principally different and actually is a special case (undocumented). $\endgroup$ Dec 2, 2014 at 19:03
  • 1
    $\begingroup$ What your call "unclear" is the expected behavior. The cases like Unevaluated[{{5 + 6}, {7 + 8}}]*1 can be understood from Trace[Unevaluated[{{5 + 6}, {7 + 8}}]*1, TraceOriginal -> True]. What happens is that at the first step the Unevaluated is stripped off and without evaluation of its contents (as expected) and you get {{5 + 6}, {7 + 8}}*1. Now further evaluation rules (built-in) of Times are applied, consider this hand-made reconstruction of Times: times[x__] := times2[x]; Trace[ times[1, Unevaluated[{{5 + 6}, {7 + 8}}]], TraceOriginal -> True]. (continued) $\endgroup$ Dec 3, 2014 at 5:43
  • 1
    $\begingroup$ As you see, at the second step you have a new expression without Unevaluated which is evaluated in the usual way. Now check this: SetAttributes[times2, HoldAll];times[x__] := times2[x]; Trace[times[1, Unevaluated[{{5 + 6}, {7 + 8}}]], TraceOriginal -> True]. You see that if times2 has the HoldAll attribute you get almost the same result as without any evaluation rules defined: evaluation stops but in any case Unevaluated fires when the first evaluation rule fires. $\endgroup$ Dec 3, 2014 at 5:47
  • 1
    $\begingroup$ In the other words, Unevaluated is already stripped off at the first step when the first evaluation rule was applied. But what will happen if the evaluation rule must not be applied? Consider this: Clear[times]; times[x__]:=times2[x]/;False;Trace[times[1,Unevaluated[{{5+6},{7+8}}]],TraceOriginal->True]. You see that at some step the Unevaluated is stripped off but finally the original expression is returned. In other words, if the evaluation does not change the original expression, Unevaluated is not stripped off in the result. $\endgroup$ Dec 3, 2014 at 5:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.