4

My goal is to have NumericQ[h[j]]=True for any j regardless of whether j may be symbolic with no defined value.

Setting NumericQ[h[j_]]=True does not work and as I understand the NumericFunction attribute only works when the input is also numeric.

One solution might be to unprotect NumericQ and then set NumericQ[h[j_]]=True but I have not tried this as I am afraid of using Unprotect. Another solution might be to define my own NumericQ function, that I can call numericq for example, and set numericq[h[j_]]=True but I would have to replace all previous NumericQ with numericq in my code and test that everything works.

  • edit *

I want to do this because I want my code to ignore certain symbols. My solution was to treat these symbols as numeric but this does not work for symbols like h[j] when j is a generic symbol. Any other function that works like NumericQ could work although I would have to change my code a bit.

userrandrand
  • 5,847
  • 6
  • 33
  • 5
    This gives off the impression of an XY problem. Surely there is a way to solve your actual problem that does not involve doing fragile things like redefining NumericQ[]. – J. M.'s missing motivation Jul 25 '22 at 17:02
  • @J.M. I agree that my question is on my current solution rather than the problem. I added an edit under * edit * to explain what the problem is. – userrandrand Jul 25 '22 at 17:17
  • 1
    Instead of unprotecting NumericQ, you could use an upvalue as in h/:HoldPattern[NumericQ[h[_]]]=True. I am not saying that it is a good idea. Btw: Somewhat surprisingly to me, even something like NumericQ[undefinedsymbol]=True gives no error. I do not understand why it gives no error, NumericQ is protected, not sure what I am missing. – user293787 Jul 25 '22 at 17:33
  • @user293787, that is a slick solution. I did not think of using an upvalue. I am quite inexperienced with upvalues. If you want to copy-paste your comment into a solution I will accept it. – userrandrand Jul 25 '22 at 17:41

2 Answers2

7

Instead of unprotecting NumericQ, one can define an upvalue for h:

h/:HoldPattern[NumericQ[h[_]]]=True;

This means that the definition is stored with h rather than with NumericQ:

UpValues[h]
(* {HoldPattern[HoldPattern[NumericQ[h[_]]]]:>True} *)

When an expression such as NumericQ[h[4]] is evaluated, then upvalue definitions for h are tried before downvalue definitions for NumericQ, hence we get True. See this tutorial.

Warning. Though I have used upvalues before with NumericQ, I do not know if it can break something.

user293787
  • 11,833
  • 10
  • 28
1

This is an extended comment and not strictly an answer. But I thought I put this here, since people that end up here for whatever reason might find it useful. For reference, I am currently using Version 12.3.

While writing the other answer, I was surprised to find that the assignment

NumericQ[undefinedsymbol] = True

gives no warning, despite NumericQ having the attribute Protected. And it works, meaning now

NumericQ[undefinedsymbol]
(* gives True *)

By contrast

NumericQ[undefinedsymbol2] = "seriously"

gives the error message

Cannot set NumericQ[undefinedsymbol2] to seriously; the lhs argument must be a symbol and the rhs must be True or False

This error would suggest that

NumericQ[undefinedsymbol3[789]] = True

would fail since undefinedsymbol3[789] is not a symbol, but it gives no error or warning. However,

NumericQ[undefinedsymbol3[789]]
(* gives False *)

I find this a bit misleading. Probably NumericQ[undefinedsymbol3[789]] = True should give an error, since without error, one assumes that the definition was recorded, when in fact it was not.

I do not know if people use this feature of NumericQ. I do not see it mentioned in the documentation.

Comment. I can understand how NumericQ[undefinedsymbol] = True can work despite the protection. For example, NumericQ could be using something similar to the following code to circumvent the protection:

myNumericQ/:Set[myNumericQ[x_Symbol],tf:(True|False)]:=(
   Unprotect[myNumericQ];
   AppendTo[DownValues[myNumericQ],HoldPattern[myNumericQ[x]]:>tf];
   Protect[myNumericQ];
   tf);
Protect[myNumericQ];
user293787
  • 11,833
  • 10
  • 28
  • 1
    As far as I know NumericQ[symbol]=True is a well-known way to attach the numeric property to a symbol and as far as I know, it is a mystery how it works. Szabolcs discusses his guess here where he also discusses why ClearAll[symbol] does not remove the numeric property from symbol. – userrandrand Jul 26 '22 at 19:25
  • @userrandrand Thank you very much, I had not seen that post! I see that Scabolcs' guess for how it works is similar to mine (but maybe mine has some obvious flaw, not sure). I think I will leave the post here for now, if only to point out the questionable behavior for NumericQ[undefinedsymbol3[789]] = True. – user293787 Jul 26 '22 at 19:36
  • For a better alternative to the AppendTo used above, see this answer. – user293787 Jul 29 '22 at 05:06