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$
  • $\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 Jan 25 '17 at 18:43
  • $\begingroup$ @MarcoB I edited the question! $\endgroup$ – MaPo Jan 25 '17 at 18:53
  • 2
    $\begingroup$ Does ConstQ = FreeQ[a|c] do what you want? $\endgroup$ – Carl Woll Jan 25 '17 at 18:56
  • $\begingroup$ No, because I must insert manually the variable a and c, ad I do not want to. $\endgroup$ – MaPo Jan 25 '17 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 Jan 25 '17 at 19:03
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$
  • $\begingroup$ I like your solution more than mine! Thank you $\endgroup$ – MaPo Jan 25 '17 at 19:21
  • $\begingroup$ @MaPo You are welcome. :-) $\endgroup$ – Mr.Wizard Jan 25 '17 at 19:27
1
$\begingroup$

I found the anwser

Nor @@ ToAvoid /@ Level[expr, Infinity]
$\endgroup$
  • 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 Jan 25 '17 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 Jan 25 '17 at 19:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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