Replacing with pattern on built-in symbols?

I have:

f[a, b] /. f[x__] -> g[x, 0] // InputForm
(* Out: g[a, b, 0] *)

Which is what I expect, but when I use a built in symbol instead of f, the result is different, for example:

Times[a, b] /. Times[x__] -> g[x, 0] // InputForm
(* Out: g[a*b, 0] *)

How could I replace the multiplication in this case to get the same result as above?

• Use Verbatim or HoldPattern, e.g., Times[a, b] /. Verbatim[Times][x__] -> g[x, 0] or Times[a, b] /. HoldPattern[Times[x__]] -> g[x, 0] – Carl Woll Mar 28 at 20:37
• You could try Times[a, b] /. Times[x___, y__] :> g[y, 0]. – Somos Mar 29 at 2:28

Amplifying my comment. The issue you are encountering is that a single argument Times evaluates (it has nothing to do with the Flat attribute of Times):

Times[x__]

x__

Hence, your code is actually doing:

Times[a, b] /. x__ -> g[x, 0]

g[a b, 0]

The way to avoid this is to prevent evaluation of the LHS pattern, with the typical methods being to use Verbatim:

Times[a, b] /. Verbatim[Times][x__] -> g[x, 0]

g[a, b, 0]

or to use HoldPattern:

Times[a, b] /. HoldPattern[Times[x__]] -> g[x, 0]

g[a, b, 0]

The problem is not that Times is a built-in symbol. As explained in another answer it stems from the evaluation of the Times in the LHS of the rule. My previous explanation (see edit) was wrong and misleading.

Having said that, one way to make it work is to simply replace the Head

In:= a b /. Times -> (g[##, 0] &)

Out:= g[a, b, 0]

If you have more complicated replacement rules you can always replace Times with a new symbol e.g. newTimes, make it Orderless if needed and then apply the rules to newTimes.

• The problem is actually an evaluation issue and not a Flat pattern matching issue. – Carl Woll Mar 29 at 17:52
• You are completely right, sorry. – MannyC Mar 29 at 18:13