1
$\begingroup$

I wrote a code like this

ConstQ[expr_]:=FreeQ[expr,a|c]

in order to verify if some expression contains a or c. Let's call these a end c variable to avoid.

I want to write down something more functional-flavoured: I declare

VariableToAvoid[_]:= False;
VariableToAvoid[a|c]:= True.

and I would like to write a function which does the same as ConstQ neither writing all the variables to avoid inside it nor making VariableToAvoid function to build a list, which doesn't seem very much functional. I'm a bit stuck. Can anyone help me?

EXAMPLE

1) non functional method

FreeQ[CentralDot[a,c],a|c];

which return False

2) functional method

ToAvoid[_]:=False;
ToAvoid[a]:=True;
ToAvoid[c]:=True;

Now I want to get the same result as above on the a generic expression, in this case CentralDot[a,c] without list the variable to avoid

AreThereMyUglyVariablesQ[CentralDot[a,c]]

of course this function must contain some ToAvoid applied to the compoment of the internal exprssion, but I do not know how

$\endgroup$
7
  • $\begingroup$ How should your function know which variables to avoid? Could you give us an example of usage of such a function, i.e. the input you expect to give it, and the output you expect to receive? $\endgroup$
    – MarcoB
    Commented Jan 25, 2017 at 18:43
  • $\begingroup$ @MarcoB I edited the question! $\endgroup$
    – MaPo
    Commented Jan 25, 2017 at 18:53
  • 2
    $\begingroup$ Does ConstQ = FreeQ[a|c] do what you want? $\endgroup$
    – Carl Woll
    Commented Jan 25, 2017 at 18:56
  • $\begingroup$ No, because I must insert manually the variable a and c, ad I do not want to. $\endgroup$
    – MaPo
    Commented Jan 25, 2017 at 18:56
  • 3
    $\begingroup$ You have to insert it some time, and with ConstQ = FreeQ[a|c] you only do it once. Then you can do ConstQ[CentralDot[1,2]], ConstQ[CentralDot[a,c]] and get True, False. $\endgroup$
    – Carl Woll
    Commented Jan 25, 2017 at 19:03

2 Answers 2

6
$\begingroup$

Possibly you are looking for PatternTest:

ToAvoid[_] := False;
ToAvoid[a] := True;
ToAvoid[c] := True;

FreeQ[CentralDot[a, b], _?ToAvoid]

  (*  False  *)

FreeQ[CentralDot[x, y], _?ToAvoid]

  (*  True   *)
$\endgroup$
2
  • $\begingroup$ I like your solution more than mine! Thank you $\endgroup$
    – MaPo
    Commented Jan 25, 2017 at 19:21
  • $\begingroup$ @MaPo You are welcome. :-) $\endgroup$
    – Mr.Wizard
    Commented Jan 25, 2017 at 19:27
1
$\begingroup$

I found the anwser

Nor @@ ToAvoid /@ Level[expr, Infinity]
$\endgroup$
2
  • 2
    $\begingroup$ This is not a desirable way to write this operation, compared to FreeQ, as it requires exhaustively listing all parts of the expression (duplication), then testing all of them with ToAvoid. FreeQ will simply scan the expression (without duplication) and it will exit early if possible. $\endgroup$
    – Mr.Wizard
    Commented Jan 25, 2017 at 19:22
  • 1
    $\begingroup$ Also you will need Level[expr, Infinity, Heads -> True] if you wish to match the default behavior of FreeQ. To provide early exit you could use AnyTrue: ! AnyTrue[Level[expr, Infinity, Heads -> True], ToAvoid] $\endgroup$
    – Mr.Wizard
    Commented Jan 25, 2017 at 19:27

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.