How do I replace content inside a Held expression without local values coming through? For example if you run the following code you get g[2] instead of g[x](the intended form).

x = 2;
Replace[HoldComplete[g["x"]], {
  y_String :> With[{
     eval = Symbol[y]},
    eval /; True]
  }, {0, Infinity}]

The following questions are related

EDIT: Although rm-rf's trick is clever it partially works. His current code adds an additional defer to the current code.

InputForm@HoldComplete[g["x"]] /. 
  s_String :> With[{x = ToExpression[s, InputForm, Defer]}, x /; True]

returns HoldComplete[g[Defer[x]]] instead of HoldComplete[g[x]]. Ultimately you could strip out the Defers which is likely what I will end up doing.


You're needlessly complicating things. The third argument of ToExpression with the Trott–Strzebonski can be used to do this:

HoldComplete[g["x"]] /. s_String :> 
    With[{x = ToExpression[s, InputForm, Defer]}, x /; True]
(* HoldComplete[g[x]] *)
  • $\begingroup$ Sequence might be used to get around this issue but I'm just running off intuition. $\endgroup$ – William Sep 15 '13 at 17:36
  • $\begingroup$ @Liam, if that's a problem why not just strip out the Defer with a replacement /. Defer[x_] :> x $\endgroup$ – Simon Woods Sep 15 '13 at 17:36
  • $\begingroup$ I modified your code slightly to the following. It works quit well. You are quit right I will stop posting partial questions especially to chat. $\endgroup$ – William Sep 15 '13 at 21:03

I hope that you will give a more complete example in the question if this is not adequate. As it stands I don't see the need to mess with context but given the earlier questions I suspect your example is not representative of what you actually wish to accomplish.

For the given example you could use something like this:

x = 2;

  SetAttributes[h, HoldAllComplete];
    /. y_String :> RuleCondition[h @@ MakeExpression@y]
    /. h[x___] :> x
] // FullForm

This is better than stripping all Defer or HoldComplete heads as it will not strip heads that were not introduced by the replace operation itself.

  • $\begingroup$ +1. Just for fun: Delete[HoldComplete[g["x"]] /. y_String :> RuleCondition@MakeExpression@y, {1,1,0}] $\endgroup$ – WReach Sep 16 '13 at 3:13

The following function ReplaceC evaluates the Replace in an alternative context and the strips the context back from the returned value.

ReplaceC[data_, rules_] := ToExpression@Replace[
     With[{body =
            Replace[x, rules, {0, Infinity}]
          HoldPattern[x] -> data, {0, Infinity}]
       }, Block[{$ContextPath = {"System`"}, $Context = "context`"},
    s_String :> StringReplace[s, RegularExpression["^context`"] -> ""],
    {0, Infinity}

Then you can run the following to get g[x].

ReplaceC[HoldComplete[g["x"]], {
  y_String :> With[{
     eval = Symbol[y]},
    eval /; True]

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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