I've been thinking about this exercise in Wagner (p. 269), but I can't answer. Can you tell me?
1 Answer
Here is a first attempt at implementing this, likely not robust.
SetAttributes[{attrQ, numberQ}, HoldAll];
attrQ[s_Symbol, attr_] := MemberQ[Attributes @ s, attr]
numberQ[x_] := NumberQ @ Unevaluated @ x || attrQ[x, Constant]
numericQ[expr_] :=
Replace[
Hold[expr],
_?numberQ | h_[__?numberQ] /; attrQ[h, NumericFunction] :> 1,
{1, -1}
] === Hold[1]
It matches the (surprising to me) behavior of NumericQ
on:
numericQ[Mod[1, 2, 3, 4] + Pi^2]
Mod::argt: Mod called with 4 arguments; 2 or 3 arguments are expected. >>
True
Replace
is used for a bottom-up collapse of the tree; for another example see:
Here is a second attempt, this time using recursion, and not attempting to avoid evaluation of the elements to allow for cleaner code.
ClearAll[attrQ, numericQ]
Attributes[attrQ] = HoldAll;
attrQ[s_Symbol, attr_] := MemberQ[Attributes@s, attr]
numericQ[_?NumberQ] = True;
numericQ[s_ /; attrQ[s, Constant]] = True;
numericQ[h_[___?numericQ] /; attrQ[h, NumericFunction]] = True;
numericQ[_] = False;
Tests:
numericQ[E^(I Pi)]
numericQ[Mod[1, 2, 3, 4] + Pi^2]
numericQ[1 + 2^"x" + Pi^2]
numericQ[7 + foo[1, 2, Pi^2]]
True
Mod::argt: Mod called with 4 arguments; 2 or 3 arguments are expected. >>
True False False
-
$\begingroup$ Interesting, yet Wagner asks about recursive implementation ... Can we agree that's one weird exercise. $\endgroup$– BoLeCommented Aug 14, 2016 at 18:28
-
$\begingroup$ @BoLe Oh, let me think about that. $\endgroup$ Commented Aug 14, 2016 at 21:35
-
1$\begingroup$ @BoLe, I suppose something along the lines of recursively checking
attrQ[head, NumericFunction]
until you hit an atom wherenumberQ[]
can be applied as the base case. $\endgroup$ Commented Aug 14, 2016 at 22:00 -
$\begingroup$ I think this is it;
___?numericQ
, nice ... $\endgroup$– BoLeCommented Aug 15, 2016 at 12:03
NumberQ[π]
, for instance, returnsFalse
. That means you have to check for a different attribute (hint, hint ;)). $\endgroup$NumericQ@Mod[1, 2, 3, 4, 5]
yieldsTrue
. Thanks for asking this! $\endgroup$NumericQ[]
: it gives aTrue
result forQPochhammer[2]
even if that does not actually evaluate to a number withN[]
. $\endgroup$_Symbol
will matchSymbol[foo, bar]
,_Real
will matchReal[1,2,3]
etc. Do any others common ones come to mind? (I foolishly thought the Q tests were more robust.) $\endgroup$