# Determine whether some expression contains a given symbol

Given a symbol t and an expression expr, how can I determine whether or not the symbol t appears somewhere in expr?

The best solution I have up with so far is:

Block[{t,s},(expr/.t->s)=!=expr]


which will return True if t is in expr, and False otherwise.

But this feels a bit like a hack because it's not really using /. because it's the right tool, but rather because /. happens to need to search through expr in order to do its unrelated task. This results in having to search through expr at least three times (I think?): once for the /., and twice for each side of the =!=, when clearly its possible to find t in only one search.

-
-1? Sure the answer is obvious once you know it, but I spent a very long time looking for an answer, and even longer trying to code my own answer. It's not like FreeQ is a terrible descriptive function name, and it's not listed in the 'Patterns' Guide, or the 'Testing Expressions' guide, or a bunch of other guides that might seem relevant to a newish user. – Ian Hincks Aug 23 '12 at 17:42
It's in "Testing and Searching List Elements" at least, but I have to agree that the omission of FreeQ[] in the "Testing Expressions" is a most unfortunate omission. – J. M. Aug 23 '12 at 17:49
@J.M. i filed FreeQ as a suggestion to be added to "Testing Expressions" – ruebenko Aug 23 '12 at 17:51
Also even if it is obvious and easy to find, at least the question makes sense, is well-written, and doesn't need mind-reading skills to answer. This is more than can be said for lots of others that people upvote – acl Aug 23 '12 at 18:44
Don't forget FreeQ takes a levelspec optional argument. Can be useful if your quarry is hiding deep inside. Also there is InternalDependsOnQ[expr,var] which attempts (operative word, that) to determine if expr has a functional dependence on x. Can be useful for tasks where detecting literal symbol presence is not quite what is wanted. Example: In[1]:= InternalDependsOnQ[f[x], x] Out[1]= True – Daniel Lichtblau Aug 23 '12 at 19:08

Try FreeQ

FreeQ[x^2, t]
(*True*)
FreeQ[x^2, x]
(*False*)

-

ruebenko provides the built-in function, but supposing FreeQ was not provided we can find another way. You are on the right track to use ReplaceAll, but it would be much better to give a result as soon as the search pattern is found.

freeQ[expr_, pat_] :=
Catch[expr /. pat :> RuleCondition@Throw[False, "freeQ"]; True, "freeQ"]


RuleCondition (1)(2)(3) is needed in the case that expr is Hold[ ] or the Throw will never evaluate.

Creating a massive expression (~1GB) and doing Timings (each in a separate session to circumvent caching) shows that this is reasonably fast.

big = Expand[(1 + x + y)^200 (2 - q)^150];

! FreeQ[big, q] // Timing


{1.03, True}

! freeQ[big, q] // Timing


{1.311, True}

Block[{q, s}, (big /. q -> s) =!= big] // Timing


{6.739, True}

Another approach that is cleaner, but perhaps less didactic, that will also return as soon as the pattern is found uses Cases:

freeQ2[expr_, pat_] :=
{} === Cases[expr, pat, {0, -1}, 1, Heads -> True]

! freeQ2[big, q] // Timing


{0.983, True}

-
 @Mr.Wizard If I am interested in testing for more than one variable I defined freeQ[a_, b_] := FreeQ[a, b] /; Length[b] <= 1; freeQ[a_, b_] := And @@ Map[FreeQ[a, #] &, b] /; Length[b] > 1  Is this the most efficient way to proceed? Why isn't it the default behaviour? – chris Aug 23 '12 at 18:57 @chris I'd suggest trying Alternatives: FreeQ[expr, x | y | z] Or do you mean something else? – Mr.Wizard♦ Aug 23 '12 at 19:00 I understand your answer as I should use freeQ[a_, b_List] := FreeQ[a, Or@@b]/; Length[b] > 1 . (I was after FreeQ taking lists) – chris Aug 23 '12 at 19:07 @chris no, I mean: freeQ[a_, b_List] := FreeQ[a, Alternatives @@ b] -- see Alternatives. – Mr.Wizard♦ Aug 23 '12 at 19:09 Thanks. I guess I have to wrap my head around Trott-Strzebonski, now. :) – rcollyer Aug 23 '12 at 19:20
show 1 more comment