Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

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: With the definition AlgebraicQ(a_) := Element(a, Algebraics), the function AlgebraicQ[Pi+E] returns Element(E+Pi, Algebraics) instead of the desired AlgebraicQ(Pi+E). Parens used in place of brackets because of platform limitations.

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]}

share|improve this question
    
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 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 at 13:58
    
On OSX and v9 AlgebraicsQ[x_Real] := Element[x, Algebraics] works as you want. –  gpap May 22 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 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 at 14:13

2 Answers 2

up vote 10 down vote accepted

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.

share|improve this answer
    
@Charles - How did you paste the image to SE? –  eldo May 22 at 14:58
    
    
    
@belisarius - Thanks for pointing me to the SE-Uploader. This smart gadget should be mentioned somewhere in the SE-Help. –  eldo May 22 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]} *)
share|improve this answer
    
Hah! So at least I wasn't too far off the mark, just careless. Thanks for pointing this out! –  Charles May 22 at 17:52

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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