For example I have some global assignments x=1;y=2;z=3 and an expression Hold[x*y/z]. How can I now extract variables {x,y,z} from this expression, do some manipulations with them and substitute their values back?
The point is to be able to this without providing variable names by hand inside of Block like so:
Block[{x,y,z},
..
]
Answer
Here is one way (I seem to remember that something similar was discussed before, but could not find it):
ClearAll[withBlockedVars];
SetAttributes[withBlockedVars,HoldRest];
withBlockedVars[Hold[expr_],code_]:=
With[
{
heldVars=
Thread[
Cases[
Unevaluated[expr],
s_Symbol/;Context[s]==="Global`"&&DownValues[s]==={}:>
HoldComplete[s],
\[Infinity],
Heads->True
],
HoldComplete
]
},
heldVars/.
HoldComplete[vars_List]:>Block[vars,code]
]
which tries to dynamically determine which symbols to block (it has some arbitrariness in the criteria). Here is how you can use this:
x = 1; y = 2; z = 3;
withBlockedVars[
Hold[x*y/z],
Hold[x*y/z] /. {x -> y + z, y -> x + z, z -> x + y}
]
(* Hold[((y + z) (x + z))/(x + y)] *)
Comments
Post a Comment