In Mathematica Cookbook recipe 2.2 I discuss a "technique" for holding arbitrary arguments. Well truth be told, this recipe is pretty lame and was not supposed to make it into the final book. This post is intended to make of for that lameness and hopefully clarify some of the bewildering multitude of ways Mathematica offers for Holding.

### The Hold Family of Attributes

Mathematica's default behavior is to evaluate every expression it sees. Here is an example.

In[1]:= a=1;b=2;c=3; d= c; e:= d; f :=e;

{a,b,c, d,e, f}

Out[2]= {1,2,3,3,3,3}

Here we associate symbols

*a*,

*b*,

*c*with integers 1, 2,3. We then associate

*d*with the value of symbol

*c*and we associate

*e*with symbol

*d*telling Mathematica not to evaluate

*d*just yet by using SetDelayed (:=). We also associate

*f*with symbol

*d*likewise delaying evaluation. Later, when we evaluate the list containing these symbols Mathematica keeps evaluating until there is nothing left to do and we get the result as integers. By using

*Trace*we can see the steps Mathematica goes through.

In[3]:= Trace[{a,b,c, d,e, f}]

Out[3]= {{a,1},{b,2},{c,3},{d,3},{e,d,3},{f,e,d,3},{1,2,3,3,3,3}}

Okay, simple enough. However, occasionally you want to write functions that act on expressions before they are evaluated. In fact, even if you never had a reason for doing so, Mathematica itself needs this capability. For example, Mathematica could not implement the function

*SetDelayed*if it did not have a way of saying "don't evaluate". Rather then creating certain functions with special no-evaluating behavior, Mathematica takes a general approach via the concept of attributes. You can inspect the attributes of a symbol using the command

*Attributes*.

In[4]:= Attributes[SetDelayed]

Out[4]= {HoldAll,Protected,SequenceHold}

Here we see SetDelayed has two attributes in the hold-family:

*HoldAll*and

*SequenceHold*. Let's explore these using our own symbols and

*SetAttributes*. Here I use symbols f1, f2 and so on without associating them with values because that is not necessary to illustrate the behavior of the attributes.

In[5]:= (* Make sure these symbols have no values or attributes*)

ClearAll[f1,f2,f3,f4,f5,f6,f7] ;

In[6]:= (* Here you can see that our list of symbols evalauates as before when we wrap f1 around it*)f1[{a,b,c,d,e,f}]

Out[6]= f1[{1,2,3,3,3,3}]

In[7]:= (*Here we use the HoldAll and associate it with f2. This says that no arguement of f2 should be evaluated*)

SetAttributes[f2, HoldAll]

In[8]:= f2[{a,b,c,d,e,f}]

Out[8]= f2[{a,b,c,d,e,f}]

In[9]:= (* It does not matter how many seperate arguments are passed, they are all held*)f2[a,b,c]

Out[9]= f2[a,b,c]

Notice the difference between evaluating

*f1*which has no attributes and

*f2*which has attribute

*HoldAll*. In essence,

*f2*acts the same as the built-in Mathematica command

*Hold*.

In[10]:= Attributes[Hold]

Out[10]= {HoldAll,Protected}

Sometimes you want only the first argument to a function to be held unevaluated. For that you use attribute

*HoldFirst*.

In[11]:= SetAttributes[f3, HoldFirst]

f3[a,b,c]

Out[12]= f3[a,2,3]

Alternatively you may want all arguments but the first to be held. Here you use

*HoldRest*.

In[13]:= SetAttributes[f4, HoldRest]

f4[a,b,c]

Out[14]= f4[1,b,c]

So far I think the mechanics of

*HoldAll*,

*HoldFirst*and

*HoldRest*should be pretty clear. Don't worry yet if you don't get why you would want to use these in your own code, I'll get to that later. Just make sure you are comfortable with the idea of using attributes to suppress Mathematica's desire to evaluate before reading on.

Okay, now I want to point out some important exceptions. Well, not really exceptions but rather clarifications.

*HoldAll*,

*HoldFirst*and

*HoldRest*do not suppress every action that Mathematica takes when it sees an expression. To illustrate this, please recall that Mathematica has a long hand way of specifying a sequence of things.

In[15]:= Sequence[1,2,3]

Out[15]= Sequence[1,2,3]

A sequence is different form a list in that Mathematica will magically flatten out sequences and splice the result into any function call.

In[16]:= f1[Sequence[1,2,3]]

Out[16]= f1[1,2,3]

In[17]:= f1[Sequence[1,2,Sequence[3,4,5]],7,8,9]

Out[17]= f1[1,2,3,4,5,7,8,9]

Now, recall that

*f2*has attributes

*HoldAll*. What do you think Mathematica does if we give

*f2*a sequence?

In[18]:= f2[Sequence[1,2,Sequence[3,4,5]],7,8,9]

Out[18]= f2[1,2,3,4,5,7,8,9]

Ah! The automatic flatting is not suppressed by

*HoldAll*nor is it suppressed by

*HoldFirst*or

*HoldRest*. The flattening out of sequences is something you usually don't want to suppress. This is why it is an exception to the rule for the standard hold family of attributes. However, you may recall that SetDelayed had another hold-like attribute called

*SequenceHold*and you can probably guess what it does!

In[19]:= SetAttributes[f5, SequenceHold]

f5[Sequence[1,2,Sequence[3,4,5]],7,8,9]

Out[20]= f5[Sequence[1,2,3,4,5],7,8,9]

Notice how the outer sequence remains. Why did the inner sequence get flattened? Simply because it is evaluated within Sequence which naturally does not have the SequenceHold attribute.

Okay, lets review. HoldAll, HoldFirst and HoldRest are attributes that suppress evaluation of specific arguments but don't suppress sequence flattening. For that you use SequenceHold. You can use one of the hold attributes together with SequenceHold to get both behaviors.

In[21]:= SetAttributes[f6, {HoldAll,SequenceHold}]

f5[Sequence[a,b,c]]

f6[Sequence[a,b,c]]

Out[22]= f5[Sequence[1,2,3]]

Out[23]= f6[Sequence[a,b,c]]

But we are not done yet! There is even a stronger form of holding that suppresses normal evaluation, sequence flattening and more! First, recall that sometimes you want to tell Mathematica that you want something to evaluate despite the presence of

*HoldAll*and friends. To see how there can be a stronger form of holding we must first consider

*Evaluate*.

In[24]:= f2[Evaluate[a,b,c]]

Out[24]= f2[1,2,3]

Evaluate is a way of saying to Mathematica that you know what you are doing and you want evaluation to take place despite the presence of HoldAll, etc.. This typically arises when you want to plot a function that you obtain by integration (or other function generating operations).

In[25]:= Attributes[Plot]

Out[25]= {HoldAll,Protected}

In[26]:= Plot[Evaluate[Integrate[Sin[x],x]], {x, 0, 2Pi}]

Out[26]:=

The attribute

*HoldAllComplete*has super-powers because it can even shield evaluation by

*Evaluate*!

In[27]:= SetAttributes[f7,HoldAllComplete]

In[28]:= f6[Evaluate[{a,b,c}]]

f7[Evaluate[{a,b,c}]]

Out[28]= f6[{1,2,3}]

Out[29]= f7[Evaluate[{a,b,c}]]

The built in command

*HoldComplete*is the counterpart to the

*Hold*command.

In[30]:= Attributes[Hold]

Attributes[HoldComplete]

Out[30]= {HoldAll,Protected}

Out[31]= {HoldAllComplete,Protected}

In[32]:= HoldComplete[Evaluate[{a,b,c}]]

Out[32]= HoldComplete[Evaluate[{a,b,c}]]

Functions with attribute

*HoldAllComplete*also suppress upvalue evaluation. I am not going to discuss up upvalues here but you can refer to the Mathematica documentation or my cookbook.

### HoldForm, Unevaluated, Defer oh my!

At this point you might think we have exhausted all the ways you can suppress evaluation but no. Mathematica has some more subtle ways you can keep its evaluation engine in check. Perhaps the easiest to understand is

*HoldForm*. This command suppresses evaluation just like

*Hold*except the command gets hidden when display in output form. The following should make the difference clear.

In[33]:= Hold[1+2]

Out[33]= Hold[1+2]

In[34]:= ReleaseHold[%]

Out[34]= 3

In[35]:= HoldForm[1+2]

Out[35]= 1+2

In[36]:= ReleaseHold[%]

Out[36]= 3

*Unevaluated*can be thought of as a temporary or one-shot

*Hold*. It suppresses evaluation the first time the Mathematica evaluator sees it but not subsequent times. The following examples are a good illustration of the difference.

In[37]:= (*first I create a simple list *)

list = {1,2,3}

Out[37]= {1,2,3}

In[38]:= (*Now lets see what happens if we try to make list list self-referential*)

list[[3]] = list; list

Out[38]= {1,2,{1,2,3}}

In[39]:= (* What happens if we doo this again using Hold? *)

list = {1,2,3};

list[[3]] = Hold[list];

list

Out[41]= {1,2,Hold[list]}

In[42]:= ReleaseHold[%]

Out[42]= {1,2,{1,2,Hold[list]}}

In[43]:= ReleaseHold[%]

Out[43]= {1,2,{1,2,{1,2,Hold[list]}}}

Okay, that is somewhat interesting. Each time we invoke

*ReleaseHold*the list expands unveiling another nested version of itself. What do you think happens if we do this experiment with

*Unevaluated*instead?

In[44]:= list = {1, 2, 3};

list[[3]] = Unevaluated[list];

listDuring evaluation of In[44]:= $RecursionLimit::reclim: Recursion depth of 256 exceeded. >>

During evaluation of In[44]:= $RecursionLimit::reclim: Recursion depth of 256 exceeded. >>

Out[46]= {1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,{1,2,Hold[{1,2,list}]}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}

Oops! We created an never ending evaluation that eventually blows up. The only way for Mathematica to finally display the "result" is for it to force a Hold into the output to put the breaks on this runaway evaluation train! The reason for this behavior is that Unevaluated allowed us to suppress evaluation of list up until the point where it made the symbol

*list*the new third element of the

*List*associated with the symbol

*list*but after that step, evaluation is no longer suppressed. So we have a symbol which contains a reference to itself and the evaluator can never stop until recursion limit is reached.

*Defer*is another function that acts like

*Hold*but will allow evaluation each time it is presented to the front-end for evaluation via the user action of hitting

**Shift-Enter**or selection the expression and using

**Evaluation In Place**. We can use the self-referential example to see this. Here each step in the expansion was created by hitting

**Shift-Enter**on the prior output.

In[47]:= list = {1, 2, 3};

list[[3]] = Defer[list];

list

Out[49]= {1,2,list}

In[50]:= {1,2,list}

Out[50]= {1,2,{1,2,list}}

In[51]:= {1,2,{1,2,list}}

Out[51]= {1,2,{1,2,{1,2,list}}}

In[52]:= {1,2,{1,2,{1,2,list}}}

Out[52]= {1,2,{1,2,{1,2,{1,2,list}}}}

So you can see Mathematica has quite a rich repertoire of functions and attributes whose sole purpose is to keep it for doing what it was designed to do - evaluate! The novice Mathematica user may be mystified by this but these features are essential to the functionality of Mathematica. In other words, the rich sets of features Mathematica provides would not be there if Mathematica did not contain mechanisms for controlling itself. Programming after all is the act where an individual exerts control over a (abstract) machine. But perhaps this explanation is a bit too metaphysical for your tastes. So lets get to some concrete examples. Consider the rich family of

*Plot*functions which take other functions as input. Notice that these all have

*HoldAll*as attributes. Think for a second why this is the case before reading on.

In[53]:= Attributes[{Plot, ParametricPlot, Plot3D}]

Out[53]= {{HoldAll,Protected},{HoldAll,Protected},{HoldAll,Protected}}

Functions that rely on delayed evaluation are typically those that are in essence little evaluation engines themselves. Think about plotting. It must take a function and evaluate it at various points so that it can map the values at those points to the graphics coordinates of points (ultimately pixels on the display device). These evaluations can not be interfered with by the normal evaluation process because in many cases that will change the input before the evaluator can do its thing. If this reasoning is correct than any function in Mathematica which repeatedly evaluates another function should utilize the Hold family of attributes. One of the simplest of these is

*Table*so let's see.

In[54]:= Attributes[Table]

Out[54]= {HoldAll,Protected}

Yep. Various forms of control flow (

*If*,

*Do*,

*Switch*) also must use held arguments for similar reasons. Another class of functions that hold arguments unevaluated are those that must act on symbolic values themselves. Examples are

*Clear*and

*AddTo*(+=). The following little program lists all such symbols in the System` context that have an attribute in the

*Hold*family.

In[55]:= Select[Names["System`*"],Length[Intersection[Attributes[#],{HoldAll,HoldFirst,HoldRest,HoldAllComplete}]]>0&]

Out[55]= {AbortProtect,AbsoluteTiming,AddTo,And,Animate,AppendTo,Arrow3DBox,ArrowBox,Assuming,Attributes,BezierCurve3DBox,BezierCurveBox,Block,BlockRandom,BSplineCurve3DBox,BSplineCurveBox,BSplineSurface3DBox,Button,CancelButton,Catch,Check,CheckAbort,CheckAll,ChoiceButtons,CircleBox,Clear,ClearAll,ClearAttributes,Compile,CompiledFunction,CompoundExpression,Condition,ConeBox,ConsoleMessage,Context,ContinuedFractionK,ContourPlot,ContourPlot3D,Control,ControlActive,ControllerManipulate,CuboidBox,CylinderBox,Debug,DebugTag,Decrement,DefaultButton,DefaultValues,Defer,Definition,DensityPlot,Dialog,DialogInput,DialogReturn,DiskBox,DivideBy,Do,DownValues,DumpSave,Dynamic,DynamicBox,DynamicModule,DynamicModuleBox,DynamicWrapper,DynamicWrapperBox,Exists,FileName,FindArgMax,FindArgMin,FindMaximum,FindMaxValue,FindMinimum,FindMinValue,FindRoot,For,ForAll,FormatValues,FullDefinition,Function,GeometricTransformation3DBox,GeometricTransformationBox,Graphics3DBox,GraphicsBox,GraphicsComplex3DBox,GraphicsComplexBox,GraphicsGroup3DBox,GraphicsGroupBox,Hold,HoldComplete,HoldForm,HoldPattern,If,Increment,Information,InsetBox,Interpretation,InterpretationBox,Line3DBox,LineBox,LineIntegralConvolutionPlot,Literal,MakeBoxes,Manipulate,MatchLocalNameQ,MemoryConstrained,MenuItem,Message,MessageName,MessagePacket,Messages,Module,Monitor,Nand,NCache,NIntegrate,Nor,NProduct,NSum,NValues,Off,On,Or,OwnValues,ParametricPlot,ParametricPlot3D,Parenthesize,Pattern,PatternTest,Piecewise,Play,Plot,Plot3D,Point3DBox,PointBox,Polygon3DBox,PolygonBox,PreDecrement,PreemptProtect,PreIncrement,PrependTo,Product,Protect,Quiet,RasterBox,Reap,RectangleBox,Refresh,RegionPlot,RegionPlot3D,Remove,RuleCondition,RuleDelayed,SampledSoundFunction,Save,Set,SetAttributes,SetDelayed,SphereBox,Stack,StackBegin,StackComplete,StackInhibit,StreamDensityPlot,StreamPlot,SubtractFrom,SubValues,Sum,Switch,SystemException,Table,TagSet,TagSetDelayed,TagUnset,Text3DBox,TextBox,TimeConstrained,TimesBy,Timing,Trace,TraceDialog,TracePrint,TraceScan,TubeBezierCurveBox,TubeBox,TubeBSplineCurveBox,Unevaluated,Unprotect,Unset,UpSet,UpSetDelayed,UpValues,ValueQ,VectorDensityPlot,VectorPlot,VectorPlot3D,WaitUntil,Which,While,With,$ConditionHold,$Failed}

Here you can see that the ultimate form of holding,

*HoldAllComplete*, is more rarely used and when it is it is for rather low-level functions.

In[56]:= Select[Names["System`*"],Length[Intersection[Attributes[#],{HoldAllComplete}]]>0&]

Out[56]= {DebugTag,HoldComplete,InterpretationBox,MakeBoxes,Parenthesize,PreemptProtect,SystemException,Unevaluated}

### Recipe 2.2 Reconsidered

In recipe 2.2 of Mathematica Cookbook I consider if it was possible to create functions that Hold other combinations of arguments than provided by

*HoldAll*,

*HoldFirst*and

*HoldRest*. The solution proposed using Hold as a pattern within the function itself. This awkward construct thus required you to use

*Hold*when you invoked the function. To further un-motivate this I presented a rather lame example in the solution.

In[57]:= array1 = Table[0, {10}]; array2 = Table[1, {10}];

arrayAssign[Hold[a_Symbol],aIndex_,Hold[b_Symbol],bIndex_]:=

Module[{},

a[[aIndex]] = b[[bIndex]];

a[[aIndex]]]

(*Assign elements 2 through 3 in array 2 to array1 *)

arrayAssign[Hold[array1],2;;3,Hold[array2],1];

array1

Out[60]= {0,1,1,0,0,0,0,0,0,0}

There are several reasons this solution is lame. First off, the example is not at all practical. There is little reason to create a function to do this when you can do the same in a one line expression. But that could be forgiven by virtue of being a purely pedagogical example. The real flaw is that this technique requires you to use Hold at the call site which is nothing at all like the behavior of functions with attributes HoldFirst, HoldRest or HoldAll. A more sensibly way to achieve the same effect is to simply use HoldAll and force evaluation where required. So to use this somewhat useless example again...

In[61]:= array1 = Table[0, {10}]; array2 = Table[1, {10}];

SetAttributes[arrayAssign2,HoldAll];arrayAssign2[a_Symbol,aIndex_,b_Symbol,bIndex_]:=

Module[{aIndex2,bIndex2},

{aIndex2,bIndex2} = Evaluate[{aIndex,bIndex}];

a[[aIndex2]] = b[[bIndex2]];

a[[aIndex2]]]

(*Assign elements 2 through 3 in array 2 to array1 *)

arrayAssign2[array1,2;;3,array2,1];

array1

Out[64]= {0,1,1,0,0,0,0,0,0,0}

## No comments:

Post a Comment