Store matched variables

Edit: I am matching and replacing a particular expression. At the same time... I want to store matched variables for later use. I got it to work with messed up code involving Block. Is there a smarter way to do this?

(*Initialize*)
variables = {}; expr = f[x] + g[x] + 3 f[y];

(*now match and replace, and storing the argument into "variables"*)
expr /. f[x_] :> Block[{}, variables = Union[variables, {x}]; fNew[x]]


Now if I type:

variables
(*output is {x,y}*)


I get the desired output.

The empty {} inside Block makes me feel I'm doing this in a kludgy way... (feel free to improve any other parts of the code too!)

• And what to do for f[] or f[x,y] ? Commented Aug 17, 2014 at 20:18
• f[] and f[x,y] do not match. Commented Aug 17, 2014 at 20:32
• but f[g[x]] should match? Commented Aug 17, 2014 at 20:43
• yes f[g[x]] that should match. Commented Aug 17, 2014 at 21:21

Sow and Reap:

{result, variables} = Reap[
expr /. f[x_] :> fNew[Sow@x]
]
variables
(* Out: {{x, y}} *)


In your original solution you do not need Block:

variables = {};
expr /. f[x_] :> (variables = Union[variables, {x}]; fNew[x])


And AppendTo can make your code shorter:

variables = {};
expr /. f[x_] :> (AppendTo[variables, x]; fNew[x])


When collecting many different values such that it may become a performance issue the Sow and Reap solution is recommended in the documentation and elsewhere. Compared to your code the alternatives do not delete duplicates, you can do this afterwards with DeleteDuplicates.

• Sow? Reap? So we're farmers now?! Nice solution. I'll wait for more answers/comments before accepting this one Commented Aug 17, 2014 at 21:00
• @QuantumDot For what it's worth I would also use Sow and Reap, but I would not put Sow inside fNew as I would not assume that it will evaluate (fNew might hold its arguments). I would use: expr /. f[x_] :> (Sow @ x; fNew @ x) Commented Aug 18, 2014 at 3:09
variables = Union@Cases[expr, f[x__] :> x, {0, Infinity}]
(* {x, y} *)

• Does this give the replaced expr as output? I should have said that outputting the replaced expr is needed, and I also need to store the variables on the side. Commented Aug 17, 2014 at 20:30
• expr /. f[x_] :> fNew[x]. I'm not quite sure what's the usefulness of combining both steps (replacement and getting variables) into one, but @Pickett's Sow and Reap do the job very nicely. Commented Aug 17, 2014 at 20:53

another version

Clear@"*"
variables = {};
expr = f[x] + g[x] + 3 f[y] + f[x + y] f[x];
var[x_] := CompoundExpression[variables = variables~Join~{x}, x]

(* usage *)
expr /. f[x_] :> fNew@var@x
variables

(* out *)
fNew[x] + 3 fNew[y] + fNew[x] fNew[x + y] + g[x]
{x, y, x, x + y}
`