6
$\begingroup$

I've been thinking about this exercise in Wagner (p. 269), but I can't answer. Can you tell me?

enter image description here

$\endgroup$
6
  • 1
    $\begingroup$ I think there are a few missing pieces in the problem description. NumberQ[π], for instance, returns False. That means you have to check for a different attribute (hint, hint ;)). $\endgroup$ Commented Aug 14, 2016 at 16:12
  • 1
    $\begingroup$ I need to read that book more carefully! I just learned something really surprising to me: invalid syntax is NumericQ. NumericQ@Mod[1, 2, 3, 4, 5] yields True. Thanks for asking this! $\endgroup$
    – Mr.Wizard
    Commented Aug 14, 2016 at 16:12
  • 1
    $\begingroup$ @Mr. Wizard, to give another pathology of NumericQ[]: it gives a True result for QPochhammer[2] even if that does not actually evaluate to a number with N[]. $\endgroup$ Commented Aug 14, 2016 at 16:21
  • $\begingroup$ @J.M. My eye have been opened. Good thing I do not write production code or I would have a lot of leaks to fix in my argument testing. One I was aware of is that _Symbol will match Symbol[foo, bar], _Real will match Real[1,2,3] etc. Do any others common ones come to mind? (I foolishly thought the Q tests were more robust.) $\endgroup$
    – Mr.Wizard
    Commented Aug 14, 2016 at 16:25
  • $\begingroup$ @Mr. Wizard, that prolly should be a separate question… :) $\endgroup$ Commented Aug 14, 2016 at 16:27

1 Answer 1

4
$\begingroup$

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
$\endgroup$
4
  • $\begingroup$ Interesting, yet Wagner asks about recursive implementation ... Can we agree that's one weird exercise. $\endgroup$
    – BoLe
    Commented Aug 14, 2016 at 18:28
  • $\begingroup$ @BoLe Oh, let me think about that. $\endgroup$
    – Mr.Wizard
    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 where numberQ[] can be applied as the base case. $\endgroup$ Commented Aug 14, 2016 at 22:00
  • $\begingroup$ I think this is it; ___?numericQ, nice ... $\endgroup$
    – BoLe
    Commented Aug 15, 2016 at 12:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.