# How do I get Mathematica to return a function call unevaluated?

How do I get Mathematica to return a function call (conditionally) unevaluated? I expect this may use the slightly-mysterious Hold function.

As a toy example, suppose I want to define AlgebraicQ such that AlgebraicQ[x] returns True or False when Element[x, Algebraics] evaluates to True or False, but otherwise to returns AlgebraicQ[x], just like the other predicate functions do. (I can't just ask if Element[x, Algebraics] == True, because this is itself unevaluated.)

Edit: The first thing that came to mind didn't work, as you can see:

I had tried this before posting, but on a recommendation I tried again with a fresh kernel (pictured above) with the same results. I also tried

AlgebraicQ[a_] := True /; Element[x, Algebraics]
AlgebraicQ[a_] := False /; ! Element[x, Algebraics]


based on an earlier suggestion but this seems not to work at all.

# Final working solution

AlgebraicQ[a_] := With[{result = Element[a, Algebraics]},
result /; MatchQ[result, True | False]]


which tests as expected:

AlgebraicQ /@ {7, Pi, Pi + E}

Out[2]= {True, False, AlgebraicQ[E + Pi]}

-
A proper predicate does not have the behavior you request, but returns True or False for any expression it is given. –  m_goldberg May 22 '14 at 13:54
@m_goldberg: The built-in AlgebraicIntegerQ has precisely the same behavior I'm describing. (How could a function possibly guarantee to return True or False when the answer is not even known to mathematicians?) –  Charles May 22 '14 at 13:58
On OSX and v9 AlgebraicsQ[x_Real] := Element[x, Algebraics] works as you want. –  gpap May 22 '14 at 14:07
@gpap: I can't imagine how, honestly. I mean, clearly that should work if I gave it a non-Real, but for a Real it should return Element[x, Algebraics] because that's what you're telling it to return. Very strange, I'd be interested to learn more about this case. –  Charles May 22 '14 at 14:10
Sorry, when I say "as you want" I mean the example you referred to (these are evaluated on a fresh kernel). –  gpap May 22 '14 at 14:13

Here's how this can be done:

ClearAll[algebraicQ]
algebraicQ[x_] := Module[{result},
result = Element[x, Algebraics];
result /; MatchQ[result, True | False]]


The key to these types of problems is usually a special use of Condition inside Block/Module/With which allows sharing localized variables between the condition and the body of Module.

-
@Charles - How did you paste the image to SE? –  eldo May 22 '14 at 14:58
–  belisarius May 22 '14 at 16:41
–  Szabolcs May 22 '14 at 16:47
@belisarius - Thanks for pointing me to the SE-Uploader. This smart gadget should be mentioned somewhere in the SE-Help. –  eldo May 22 '14 at 17:50

Your earlier approach would have worked if you had actually tested the argument to the function (a) rather than the undefined symbol x...

AlgebraicQ[a_] := True /; Element[a, Algebraics]
AlgebraicQ[a_] := False /; ! Element[a, Algebraics]
AlgebraicQ /@ {7, Pi, Pi + E}

(* {True, False, AlgebraicQ[E + Pi]} *)

-
Hah! So at least I wasn't too far off the mark, just careless. Thanks for pointing this out! –  Charles May 22 '14 at 17:52