Take the 2-minute tour ×

I am writing a code that manipulates expressions that contains functions with an arbitrary number of arguments. An example expression is

expr = x f[a, b, c, d] - 4 f[b, a, d] + z f[] + f[a, b, d] - f[a]f[b,d]

What I would like to do is to make my code to be a little user-friendly by making it throw a message if the expression is invalid. Basically, the only symbols allowed to appear in f are allowedList={a,b,d}, and so I probably need to somehow use Scan to check through expr. (The above example should yield an 'error' since the first term has a c in it.)

To make answering easier, please assume that the input expr will be such that all arguments will have Head = Symbol. But please allow for the possibility that multiple fs could be multiplied together.

share|improve this question
add comment

3 Answers

up vote 5 down vote accepted

This function yields True if the expression expr is valid, otherwise it yields False:

validExpressionQ[ expr_, allowedList_List] := 
  Union @ Cases[ Variables[expr], f_[x___] :> x, Infinity] == Union @ allowedList

now we have, e.g.

validExpressionQ[ x f[a, b, d] - 4 f[b, a, d] + z f[] + f[a, b, d] - f[a] f[b, d], 
                  {a, b, d}]
                  {a, b, d}]
share|improve this answer
I guess it should work even if f has DownValues –  belisarius Jan 29 at 13:19
not sure, BTW :) –  belisarius Jan 29 at 13:20
Very nice. In the right hand side, would it still work if I replaced Union @ allowedList with just allowedList? –  QuantumDot Jan 29 at 14:35
@QuantumDot No, Union sorts the list, it might be replaced with Sort but then it doesn't delete duplicates. –  Artes Jan 29 at 20:38
add comment

A possibility is to define a support function:

EDIT: Thanks to Simon Woods' comment: .. instead of __

check[(a | b | d) ..] := 1;
check[___] = Indeterminate;

The substitution

expr /. f-> check

contains Indeterminate if f has arguments not allowed.


If[FreeQ[expr /. f -> check, Indeterminate], "ok", "error"]

returns "error" for your example and "ok" if the arguments are acceptable.

share|improve this answer
check[a, b] returns Indeterminate. Perhaps you intended to use RepeatedNull rather than BlankSequence ? –  Simon Woods Jan 29 at 21:30
I just posted something very similar before reading this answer. +1! Nevertheless I think my code has advantages. –  Mr.Wizard Jan 30 at 15:52
add comment

Since it seems that evaluation of the expression is specifically permitted let's leverage that:

check[expr_, f_, pat_] := FreeQ[expr /. f[pat ...] -> 1, _f]

check[expr, f, a | b | d]
check[expr, f, a | b | c | d]


I used Alternatives instead of List to make this cleaner, but you can always Apply Alternatives if needed.

If for some reason you don't like the method above, here is my take on Artes's method:

check2[expr_, f_, args_] :=
  {} === Complement[Cases[expr, f[x___] :> x, -2], args]

check2[expr, f, {a, b, d}]
check2[expr, f, {a, b, c, d}]

share|improve this answer
add comment

Your Answer


