2

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.

William
  • 7,595
  • 2
  • 22
  • 70

3 Answers3

6

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]] *)
rm -rf
  • 88,781
  • 21
  • 293
  • 472
4

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;

Module[{h},
  SetAttributes[h, HoldAllComplete];
  HoldComplete[g["x"]]
    /. y_String :> RuleCondition[h @@ MakeExpression@y]
    /. h[x___] :> x
] // FullForm
HoldComplete[g[x]]

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.

Mr.Wizard
  • 271,378
  • 34
  • 587
  • 1,371
  • +1. Just for fun: Delete[HoldComplete[g["x"]] /. y_String :> RuleCondition@MakeExpression@y, {1,1,0}] – WReach Sep 16 '13 at 03:13
0

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[
    ToBoxes[
     With[{body =
        ReleaseHold@Replace[HoldComplete@MakeBoxes[
            Replace[x, rules, {0, Infinity}]
            ],
          HoldPattern[x] -> data, {0, Infinity}]
       }, Block[{$ContextPath = {"System`"}, $Context = "context`"},
       ToExpression@body]
      ]
     ],
    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]
  }]
William
  • 7,595
  • 2
  • 22
  • 70