7
$\begingroup$

There is an attribute NumericFunction in Mathematica that can do the following job:

Attributes[f] = {NumericFunction}; NumericQ[f[1,2,3,4]] 

then returns true. However, the following return false

NumericQ[f[{1,2,3,4}]]; NumericQ[f[1,{2},3,{4}]] 

which makes sense by Documentation on NumericFunction. However, I want to define a function $f$ that returns True even in above cases, how can this be achieved?

Curiously, functions like HypergeometricPFQ has Attributes NumericFunction, but NumericQ[HypergeometricPFQ[{1, Sqrt[2]}, {Pi}, 1/3]] still returns true despite having lists in its arguments, why?

My goal is to define an f such that all expressions like f[1,{2},3,{4}], 1+5*f[1,{2},3,{4}], Sin[1+5*f[1,{2},3,{4}]] returns true upon NumericQ. How can this be done?

Thank you.


Update: After much thoughts, I think I found a solution:

SetAttributes[f, NumericFunction]; Unprotect[NumericQ]; $numericflag = 0; NumericQ[expr_] /; FreeQ[expr, f] == False && $numericflag == 0 := Block[{bool}, $numericflag = 1; bool = NumericQ[expr /. f[x__] :> f @@ Flatten[{x}]]; $numericflag = 0; Return[bool]]; Protect[NumericQ]; 

it works as expected: NumericQ[Pi + 58 + f[2, 3, {4, 4}]], NumericQ[Sin[f[2,{3,{0,0}}]]] all return true.

$\endgroup$
2
  • 2
    $\begingroup$ I don't have a rigorous answer, but it appears that it is linked to the fact f is not defined. If you define f (e.g. f[l___]:=1 the result of NumericQ@f[{1},2,3] become True $\endgroup$ Commented May 14, 2020 at 13:21
  • 4
    $\begingroup$ @youyou Isn't it because f evaluates to 1 first? NumericQ doesn't have any Hold* attributes. $\endgroup$ Commented May 14, 2020 at 15:27

2 Answers 2

2
$\begingroup$

I thought @swish would incorporate my comment, but let me put it here, since it is an answer to the question. In the following, the arguments of f can be numbers or any sort of nested lists of numbers.

f /: NumericQ[f[args___]] /; VectorQ[Flatten@{args}, NumericQ] := True; NumericQ[f[1, 2, 3, 4]] NumericQ[f[{1, 2, 3, 4}]] NumericQ[f[1, {2}, 3, {4}]] NumericQ[f[x]] (* False -- should check both cases T, F *) NumericQ[f[]] (* True -- same as `NumericQ[Sin[]]` *) (* True True True False True *) 

Update

@pisco points out that the above does not work if f[..] is nested inside other numeric expressions. There is an internal function that could be used to replace NumericQ:

ClearAll[f]; Attributes@f = {NumericFunction}; Internal`WouldBeNumericQ[2 + f[1, {2}, 3], {}] (* True *) 

The last list is a list a variables, the function tests whether f would be numeric if numeric values were substituted for the variables.

$\endgroup$
2
  • $\begingroup$ Thank you for your answer. However, one major shortcoming seems that NumericQ[1+f[1,2,3]] returns false. If one sets NumericFunction attributes to f, this returns true. However, NumericQ[1+f[1,{2},3]] still returns false. How to tackle this? $\endgroup$ Commented May 28, 2020 at 5:43
  • 1
    $\begingroup$ @pisco I added a workaround to my answer. Feel free to unaccept if it's not satisfactory. The workings of NumericQ are hidden from Trace. I suspect there are some optimizations in C that get around my first def. $\endgroup$ Commented May 28, 2020 at 13:16
2
$\begingroup$

There is a slight problem with NumericQ, that prevents one to define your UpValues with it. So that would not work as expected:

f /: NumericQ[_f] := True 

But manually

UpValues[f] = {HoldPattern[NumericQ[_f]] :> True}; 

it works as expected:

NumericQ[f[{1, 2, 3, 4}]] NumericQ[f[1, {2}, 3, {4}]] (* True *) (* True *) 
$\endgroup$
1
  • 2
    $\begingroup$ I think the solution is a little over-eager :) -- Try NumericQ[f[1, {2, t}, 4]] which should return False. I think the def. f /: NumericQ[f[args___]] /; VectorQ[Flatten@{args}, NumericQ] := True is more on-target. $\endgroup$ Commented May 14, 2020 at 17:33

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.