Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

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},
  ..
]
share|improve this question

2 Answers 2

up vote 4 down vote accepted

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)] *)
share|improve this answer
    
It works perfectly! Thank you! –  swish Sep 21 '13 at 16:48
    
@swish Was glad to help. Thanks for the accept. –  Leonid Shifrin Sep 21 '13 at 17:11

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.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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