%mathpiper,def="HasExpr"

/// HasExpr --- test for an expression containing a subexpression
/// for checking dependence on variables, this may be faster than using VarList or IsFreeOf and this also can be used on non-variables, e.g. strings or numbers or other atoms or even on non-atoms
// an expression contains itself -- check early
10 # HasExpr(_expr, _atom) _ IsEqual(expr, atom) <-- True;
// an atom contains itself
15 # HasExpr(expr_IsAtom, _atom) <-- IsEqual(expr, atom);
// a list contains an atom if one element contains it
// we test for lists now because lists are also functions
// first take care of the empty list:
19 # HasExpr({}, _atom) <-- False;
20 # HasExpr(expr_IsList, _atom) <-- HasExpr(First(expr), atom) Or HasExpr(Rest(expr), atom);
// a function contains an atom if one of its arguments contains it
30 # HasExpr(expr_IsFunction, _atom) <-- HasExpr(Rest(FunctionToList(expr)), atom);

%/mathpiper



%mathpiper_docs,name="HasExpr",categories="User Functions;Predicates"
*CMD HasExpr --- check for expression containing a subexpression
*STD
*CALL
	HasExpr(expr, x)

*PARMS

{expr} -- an expression

{x} -- a subexpression to be found



*DESC

The command {HasExpr} returns {True} if the expression {expr} contains a literal subexpression {x}. The expression is recursively traversed.

Note that since the operators "{+}" and "{-}" are prefix as well as infix operators, it is currently required to use {ToAtom("+")} to obtain the unevaluated atom "{+}".

*E.G.

In> HasExpr(x+y*Cos(Ln(z)/z), z)
Result: True;
In> HasExpr(x+y*Cos(Ln(z)/z), Ln(z))
Result: True;
In> HasExpr(x+y*Cos(Ln(z)/z), z/Ln(z))
Result: False;

*SEE HasExprArith, HasExprSome, FuncList, VarList, HasFunc
%/mathpiper_docs