How to make use of NumericQ[x] = True (and use it safely)?

Basic Issue:

I'm trying to understand the proper use of NumericQ's "magical" capabilities. Please consider the examples below. Actual question and some links are at the very end.

Example 1:

Many of you are aware that NumericQ can be used as follows, without unprotecting:

In[1]:=
Remove[x, y];
NumericQ[x] = True;
(*and apparently using TagSet instead of Set makes no difference because \
you can't direct, let alone see, where this type of info is stored \
anyways.*)


The following output is as expected:

In[3]:=
NumericQ[x]
NumericQ[y]

Out[3]= True
Out[4]= False


Go ahead and make the following assignment:

In[5]:= x = y

Out[5]= y


The following behavior is interesting, but quite reasonable. It seems logical that setting x to y would somehow globally overwrite the "magical" numeric property:

In[6]:=
NumericQ[x]
NumericQ[y]

Out[6]= False
Out[7]= False


Hmmm... #1

...Well, at least I thought it would have 'overwritten' the behavior!!

In[8]:=
(*Note: Could also use Clear[x] or ClearAll[x] *)
x =.
NumericQ[x]

Out[9]= True


Example 2:

Now suppose we had made the assignment x = y first (before evaluating NumericQ[x] = True):

In[12]:=
Remove[x, y];
x = y

Out[13]= y


Hmmm... #2

Now Mathematica has pushed the numerical property onto y as well.

In[14]:=
NumericQ[x] = True
NumericQ[y]

Out[14]= True
Out[15]= True


Question:

How can one put NumericQ[x] = True to good/powerful use---and just as importanltly, in light of the above examples, how can it be used safely? (i.e., Can this behavior be localized somehow? Used safely within a package?---intuition makes me wonder if the only way to isolate the behavior would be to store impacted symbols in a junk context or something.)

@Szabolcs 'Mathematica Tricks' page; scroll down about half way or search for NumericQ: http://web.ift.uib.no/~szhorvat/mmatricks.php

-
Daniel's reply in the MathGroup thread gives a lot of relevant details on why this was implemented and how it was intended to be used. That would probably be the answer you're looking for –  rm -rf Sep 2 '12 at 17:26
You may also want to look at this discussion –  Leonid Shifrin Sep 2 '12 at 18:48

The behaviour you observed is completely independent of NumericQ. It could also be seen with a function foo which has the initial definition foo[_]=False.

Example 1:

Initially you define NumerixQ[x]=True, which tells Mathematica that whenever it evaluates the expression NumericQ[x], it should evaluate to True. Since for symbols, it is pre-defined to return False, it will do so for y (Out[3], Out[4]).

Then you define x=y and evaluate NumericQ[x]. Since NumericQ doesn't have any special attributes, the normal evaluation order applies, which means to first evaluate the argument (evaluating x gives y), and then to evaluate the resulting expression NumericQ[y] which of course gives False. Note that NumericQ is not applied to x (which would still give true).

Next, you remove the definition of x (but still don't touch the definition of NumericQ where the value of NumericQ[x] is still stored). Therefore the symbol x is self-evaluating again, and you again evaluate NumericQ[x], resulting in True.

Example 2:

Here you start with x=y, which makes x evauate to y. When you then use NumericQ[x]=True you trigger what I consider the most confusing behaviour of Mathematica (which still isn't directly related to NumericQ): While Set (=) has the attribute HoldFirst, that does not mean that the left hand side isn't evaluated at all; the argument x is still evaluated to y before the assignment is evaluated, so the assignment that is ultimately evaluated is NumericQ[y]=True. Your subsequent evaluation NumericQ[y] therefore gives True. You can see this confusing behaviour also in the following example:

x = y
f[x] = 3
x =.
{f[x], f[y]}
(*
==> {f[x], 3}
*)

-
What you wrote seems helpful, but please give me some time to digest. I'm still unclear as to when using NumericQ in this manner can be of use though. Putting my inquiry another way, the behavior is certainly confusing (to me at least) and I consider that a 'cost' of use, so what are the potential 'benefits'? And is it possible to minimize potential confusion by localizing somehow? –  telefunkenvf14 Sep 2 '12 at 20:25
Thanks for the answer. The explanation of 'example 2' helps greatly. As for 'example 1', I guess part of my worry/confusion/wonder is that, although I use Unset in the example, ClearAll[x] doesn't kill NumberQ[x]:=True either--- only Remove[x] does. (Not apparent to me why that would be the case, I guess.) –  telefunkenvf14 Sep 10 '12 at 11:17
@telefunkenvf14: The reason would be that with NumberQ[x]:=True you add a new rule to NumberQ, not to x. However even with NumericQ[x]^:=True (which should normally associate the definition with x instead of NumericQ), ClearAll[x] still doesn't seem to work. Strange. Apparently there's a special handling for assignments to NumericQ which isn't properly accounted for by ClearAll. Of course you can always add an explicit NumericQ[x]=False after ClearAll. –  celtschk Sep 10 '12 at 12:46

Let's see if this clarifies your issues with the usefulness of the construct. Probably not because I am not sure I understood them.

You want to have some numeric value, represented by a symbol. A constant, a unit, who knows. You do

NumericQ[symb]=True


Now, any function defined to only receive numeric input (_?NumericQ) will know it can take symb as an argument, and also numeric functions applied to symb. This becomes more useful coupled with a definition like

N[symb]=2958429384523542.3543;


These two definitions would allow you to keep your results exact and symbolic while at the same time being able to turn them into numeric values when needed and use Mathematica's numerical functions.

-