53
$\begingroup$

In version 10, Mathematica not only added Inactive / Activate but also highlighted this change in the "New in 10" page (in Core Language Enhancements). Thus, I suppose it should be something useful. However, I didn't understand in which sense it is better than the good old Hold (HoldForm) / ReleaseHold mechanism. I noticed a few differences, but all of those are minor:

(1) Inactive objects are printed in a lighter color. HoldForm objects are printed in normal color.

(2) There is an IgnoringInactive function to include inactive objects into pattern matching.

It would be nice to hear if there are more important differences.

$\endgroup$
0

4 Answers 4

41
$\begingroup$

Updated

Both Hold and Inactive block evaluation; the key difference is that Inactive is meant to be wrapped around heads rather than a whole expression. Inactivate does this.

Inactivate[1 + 2 + 3 * 4 ^ 5 ] // FullForm
Inactive[Plus][1, 2, Inactive[Times][3, Inactive[Power][4, 5]]]

It is of course possible to use Inactive directly, and it will behave like any symbol with holding attributes.

Inactive[1 + 2 + 3 * 4 ^ 5] // FullForm
Inactive[Plus[1, 2, Times[3, Power[4, 5]]]]

But in general there is no reason to use it this way. Note that while Activate and ReleaseHold are comparable, there is no analog to Inactivate. The point is to use these auxiliary functions.

Because Inactivate wraps heads, it can accept an optional second argument constraining which heads to inactivate.

Inactivate[1 + 2 + 3 * 4 ^ 5, Plus] // FullForm
Inactive[Plus][1, 2, 3072]

Activate can similarly accept an optional second argument.

Inactivate[1 + 2 + 3 * 4 ^ 5];
Activate[%, Power] // FullForm
Inactive[Plus][1, 2, Inactive[Times][3, 1024]]

Another interesting consequence of using Inactivate is that atomic symbols will get evaluated.

Hold @ {$WolframUUID}
Hold[{$WolframUUID}]
Inactivate @ {$WolframUUID}
{"0e2497dc-9281-48f3-8e84-14b5e2587446"}
$\endgroup$
5
  • 1
    $\begingroup$ Thanks! But why don't they just add pattern matching or tags to Hold and ReleaseHold, but instead do something new and parallel? $\endgroup$
    – Yi Wang
    Commented Jul 11, 2014 at 17:39
  • $\begingroup$ I think it is just a design decision. In my opinion, the functionality is sufficiently different that it makes sense to use a different set of symbols. (Recall that Unevaluated also exists.) $\endgroup$
    – mfvonh
    Commented Jul 11, 2014 at 20:04
  • 3
    $\begingroup$ @YiWang Hold[A,B] Already has a working definition (it will hold the sequence of elements), so if you add some sort of tags functionality to Hold you need to either get really creative or break backwards compatibility. But really, I don't think that there is any reason why Inactivate couldn't just wrap holds around heads and activate remove these holds. But personally I prefer the distinction. $\endgroup$
    – jVincent
    Commented Jul 11, 2014 at 20:24
  • $\begingroup$ But couldn't the effect of Inactivate also be achieved using Hold with SetAttributes[MakeHeld, HoldAll]; MakeHeld[a_[b___]] := MakeHeld[a][b]; MakeHeld[a_] := Hold[a]? $\endgroup$
    – celtschk
    Commented Jul 21, 2014 at 20:34
  • $\begingroup$ @celtschk Certainly; with that I only meant to highlight that they are intended to be used differently, but how you use them is of course flexible. The more subtle advantages of a different head are nicely pointed out in the other answers, and of course by the OP (IgnoringInactive). $\endgroup$
    – mfvonh
    Commented Jul 23, 2014 at 13:23
19
$\begingroup$

One difference is that NDSolve directly supports Inactive. It can be used to specify operators such as divergence ($\nabla\cdot$) without automatically evaluating them to components. This is described here.

$\endgroup$
12
$\begingroup$

Although mfvonh's answer is a nice summary of Inactive formal properties, I think it misses several important points, which are both shown in the "Scope" and "Applications" section of the documentation. For me the main point seems to be (2), as I don't know how this could be achieved using Hold.

1) Inactive can be used to illustrate formal mathematical identities, e.g.,

Table[Block[{e = Inactivate[n + m]}, e == Activate[e]], {n, 0, 3}, {m,
 0, 3}] // Grid // TraditionalForm

2) It can be used in formal mathematical manipulations (as hinted at by Szabolcs' answer), e.g.,

D[Inactive[Integrate][f[x], {x, a[x], b[x]}],x]
(*-f[a[x]] Derivative[1][a][x] + f[b[x]] Derivative[1][b][x]*)

3) It can be used for easy programmatic code transformation, as Inactivate automatically wraps around all heads:

 def = Inactivate[for[f_, max_] := For[x = 1, x < max, x++, Print@x]];
 def/.Inactivate[For[i_ = init_, i_ < max_, i_++, body_] :> Do[body, {i, init, max}]]
 (*forSquares[f_,max_]:=Do[Print[f[x^2]],{x,1,max}]*)

So the use cases are quite different from the ones of Hold/ReleaseHold. I don't think (2) could be easily achieved with Hold, and (3) is definitely more elegantly solved by using Inactivate.

$\endgroup$
2
  • $\begingroup$ (2) is very interesting. But I didn't get the point of (1). When I run Block[{e = HoldForm[23 + 11]}, e == ReleaseHold[e]], I get the same displayed result (though different InputForm). $\endgroup$
    – Yi Wang
    Commented Jul 21, 2014 at 10:48
  • $\begingroup$ @YiWang Oops, good point :) I didn't think of HoldForm because I never use it. The real point is probably in a more elaborate example (see edit). Now I'm crossing my fingers that I didn't overlook something else... $\endgroup$
    – sebhofer
    Commented Jul 21, 2014 at 10:54
9
$\begingroup$

I think the basic answer to your question is:

1) If you want absolute control over revaluation, nothing beats good old HoldComplete. It will be there to the end of time.

2) Inactive meant for much more targeted/slippy applications. As such, it only wraps heads, not all arguments (as already noted by mfvonh). You can control which heads get inactived. And math is allowed to occur when there is an unambigous answer to an operation, which absolutely cannot happen with Hold. My personal favourite:

In[2]:= Curl[Inactive[Grad][f[x, y], {x, y}], {x, y}]
Out[2]= 0

In keeping with these applications, Inactivate ignores certains heads but default, most notably List. This way, the strucutre of your data is unchanged and tensorial operations can be performed--very important in NDSolve. The basic idea is Inactive[f] represents an inactive form of a desired operation, not some held expression which will be modified on manually.

$\endgroup$

Your Answer

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

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