"logo.gif"  
Main
Read Online
Download PDF
Additional resources
Revision history
Known typos/bugs
Report a bug
License terms
About the author
"node408_1.gif" "node408_2.gif" "node408_3.gif"

4.9.7.2 Advanced topic: Hold attributes and pattern-matching

While the general topic of Hold attributes is a bit too advanced for us now (since it requires a much more thorough discussion of the evaluation process), let me mention   one important point. This is, Hold attributes affect pattern-matching.   Consider the following function.

"node408_4.gif"

It is supposed to square any expression of the form Sin[anything],  and issue a message for all other inputs. We can try it:

"node408_5.gif"

"node408_6.gif"

In the last input,  Sin[Pi] was evaluated first, leading to f[0], which  led to a "Not sine" message. Let us now add the attribute:

"node408_7.gif"

And test the same input again:

"node408_8.gif"

"node408_9.gif"

What happened with the last output is that the presence of Hold attribute made a function to evaluate "branches before leaves", and then it had a chance to "see" Sin[Pi] before it evaluated to 0, and thus the first definition applied.

All right, this is all known stuff, we discussed the non-standard evaluation before. But now, let us do it a bit differently :

"node408_10.gif"

"node408_11.gif"

For us, it is obvious that <a> is  Sin[b], so this behavior looks like a bug. It isn' t however: Hold attribute means that the argument is held unevaluated before the rules associated with the function apply. If we supply the direct Sin[something], then, while Sin[something] is not evaluated, the function can test the head of the argument (which is Sin) and thus the first definition (associated with Sin[something]) applies. If however the value of the expression is stored in another variable, then by the time the pattern-matching takes place, there is no way for  the function to test the head of an expression Sin[b] - all it has is a symbol <a> (again because <a> this time is held unevaluated) . This behavior may lead to rather subtle bugs in user-defined functions which use Hold attributes. One way out in this case would be to redefine the function as follows:

"node408_12.gif"

Here, by using Evaluate, we override the Hold attribute in that particular place and instruct the argument inside Head command to be evaluated.  Now :

"node408_13.gif"

"node408_14.gif"

The case with a Sin[Pi] is lost however :

"node408_15.gif"

"node408_16.gif"

If we think of it, this is still a more logical behavior, since it is more logical (or should I say more robust) to test the head of fully evaluated expression than the one which will evaluate to something else. If one wants to catch both cases (something that was Sin[expr] or something that will become Sin[expr]), this is also possible:

"node408_17.gif"

"node408_18.gif"

"node408_19.gif"

One may ask when in practice do such situations occur. More often than one may think, in fact. As a simple example, an expression may be assigned to a local variable in one function, which then passes this variable (with the "pass-by-reference" semantics) to  another function which is supposed to both do a type-check and subsequently modify this variable. Such cases are relatively rare just because pass-by-reference semantics and in-place modifications are rarely used in "usual"  Mathematica programming, but once you choose to program in this style (which  occasionally is a good option), these sorts of problems will pop up much more often.

"node408_20.gif" "node408_21.gif" "node408_22.gif"

Created by Wolfram Mathematica 6.0  (05 February 2009) Valid XHTML 1.1!