4
$\begingroup$

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},
  ..
]
$\endgroup$

2 Answers 2

6
$\begingroup$

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)] *)
$\endgroup$
2
  • $\begingroup$ It works perfectly! Thank you! $\endgroup$
    – swish
    Sep 21, 2013 at 16:48
  • $\begingroup$ @swish Was glad to help. Thanks for the accept. $\endgroup$ Sep 21, 2013 at 17:11
1
$\begingroup$

I'm not certain if I'm understanding your request correctly, but if you are looking simply to make replacements using the symbols that appear in the expression, you can make do with using HoldPattern. So using Leonids example, you would use:

Hold[x*y/z] /. { HoldPattern[x] :> y + z^x, 
                 HoldPattern[y] :> x + z, 
                 HoldPattern[z] :> x + y}
(* Hold[((y + z^x) (x + z))/(x + y)] *)

Since it's a delayed rule the inserted expressions aren't evaluated, and HoldPattern prevents the left hands of the rules from evaluating.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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