I have three expressions a[x, y], b[x, y], c[x, y]
that act as placeholders for functions of two variables x,y
. Consider the following substitution:
a[x, y]/(b[x, y] c[x, y]) /. f_[x1_, y1_] :> f[2 x1, 3 y1]
a[2 x, 3 y]/(64 b[x, y]^3 c[x, y]^3)
In the output we see that the numerator expression was substituted properly, but in the denominator the pattern f_
registered for the head Power
instead of looking for my own expressions. Of course I can fix this by:
a[x, y]/(b[x, y] c[x, y]) /. a[x1_, y1_] :> a[2 x1, 3 y1] /.b[x1_, y1_] :> b[2 x1, 3 y1] /. c[x1_, y1_] :> c[2 x1, 3 y1]
a[2 x, 3 y]/(b[2 x, 3 y] c[2 x, 3 y])
which gives the desired output. But this amounts to writing three times as many substitution directives and is therefore inconvenient. To fix the first example, I tried using /. f_Symbol[x1_, y1_] :> f[2 x1, 3 y1]
or /. f_[x1_, y1_]/;Head[f]===Symbol :> f[2 x1, 3 y1]
, but this does not correct it. Is there a way to write a proper substitution that works with headers and does not act on built in functions? Thanks for any suggestions.
EDIT:
Just noticed that Head[Power]
actually returns Symbol
, which is kind of weird. I would have expected it to return e.g. Function
, or Directive
, or something along the lines. (If one unprotects and clears the Power
function, then I would again expect Head[Power]
to return Symbol
of course. But maybe that's just me...)
Answer
The best method I am aware of to handle this kind of problem is to filter by context.(1)
SetAttributes[user, HoldFirst]
user[s_Symbol] := Context@Unevaluated@s =!= "System`";
a[x, y]/(b[x, y] c[x, y]) /. f_?user[x1_, y1_] :> f[2 x1, 3 y1]
a[2 x, 3 y]/(b[2 x, 3 y] c[2 x, 3 y])
One could include other contexts in the exclusion besides System, or use the inverse and test only for user symbols existing in the "Global`"
context. Without additional examples my example is as specific as I can make it.
Regarding the unusual evaluation of the ?
operator (PatternTest
) please see:
Comments
Post a Comment