# 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

based on Szabolcs' answer:

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.

At this point I should note that the convention seems to be that any function that ends in ...Q will always return either True or False. Consider EvenQ vs Positive. EvenQ[x], with x undefined, gives False. Positive[x] stays unevaluated. I know of only a very few edge cases which don't follow this. Naming this algebraicQ would violate that convention.

-
@Charles - How did you paste the image to SE? – eldo May 22 '14 at 14:58
– Dr. 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
@Agreeing with the convention! I strongly hope that WRI sticks to this, minimizing headaches to sort out non-binary cases (True/False/unevaluated). – István Zachar Jul 5 at 12:27

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