6
$\begingroup$

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.

$\endgroup$

3 Answers 3

5
$\begingroup$

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}]
True
validExpressionQ[ x f[a, b, c, d] - 4 f[b, a, d] + z f[] + f[a, b, d] - f[a] f[b, d],
                  {a, b, d}]
False
$\endgroup$
4
  • $\begingroup$ I guess it should work even if f has DownValues $\endgroup$ Jan 29, 2014 at 13:19
  • $\begingroup$ not sure, BTW :) $\endgroup$ Jan 29, 2014 at 13:20
  • $\begingroup$ Very nice. In the right hand side, would it still work if I replaced Union @ allowedList with just allowedList? $\endgroup$
    – QuantumDot
    Jan 29, 2014 at 14:35
  • $\begingroup$ @QuantumDot No, Union sorts the list, it might be replaced with Sort but then it doesn't delete duplicates. $\endgroup$
    – Artes
    Jan 29, 2014 at 20:38
2
$\begingroup$

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.

Concluding:

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

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

$\endgroup$
2
  • $\begingroup$ check[a, b] returns Indeterminate. Perhaps you intended to use RepeatedNull rather than BlankSequence ? $\endgroup$ Jan 29, 2014 at 21:30
  • $\begingroup$ I just posted something very similar before reading this answer. +1! Nevertheless I think my code has advantages. $\endgroup$
    – Mr.Wizard
    Jan 30, 2014 at 15:52
1
$\begingroup$

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

True

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

True
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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