Diciness with extracting things from Hold'd expression

Suppose I have a list of rules param_> value, where params are characters that can have values ​​assigned to them. For instance:

{a, b, c} = {1, 2, 3};
x = Hold[{a->1, b->2, c->3}];

I need a list enclosed in Hold, otherwise it will be evaluated at {1-> 1, 2-> 2, 3-> 3}. (I am open to any alternatives to Keep there if it makes all this easier.)

Now suppose I want to convert x to this:

{"a"->1, "b"->2, "c"->3}

The following function will do this:

f[h_] := Block[{a,b,c}, ToString[#[[1]]]->#[[2]]& /@ ReleaseHold@h]

My question is: Can you write a version of f where the list of characters {a, b, c} need not be explicitly specified?

+3
source share
3 answers

Here is a way to use Unevaluated :

In[1]:= {a, b, c} = {1, 2, 3};

In[2]:= x = Hold[{a -> 1, b -> 2, c -> 3}];

In[3]:= ReleaseHold[
 x /. (symb_ -> e_) :> ToString[Unevaluated[symb]] -> e]

Out[3]= {"a" -> 1, "b" -> 2, "c" -> 3}
+5
source
{a, b, c} = {1, 2, 3};
x = Hold[{a -> 1, b -> 2, c -> 3}];
f[x_] := Cases[x, HoldPattern[z_ -> y_] :> 
                  StringTake[ToString[(Hold@z)], {6, -2}] -> y, 2];
f[x] // InputForm

Of:

{"a" -> 1, "b" -> 2, "c" -> 3} 

, , , , .

+1

, , , . HoldPattern , , Hold , , ReleaseHold.

In[1]:= {a, b, c} = {1, 2, 3};

Unevaluated :

In[2]:= x = Thread[HoldPattern /@ Unevaluated[{a, b, c}] -> Range[3]]
Out[2]= {HoldPattern[a] -> 1, HoldPattern[b] -> 2, HoldPattern[c] -> 3}

, , . , , . , OwnValues DownValues, . HoldPattern Verbatim:

In[3]:= f[rules_] :=
         Replace[rules,
          HoldPattern[Verbatim[HoldPattern][s_Symbol] -> rhs_] :>
           With[{string = ToString[Unevaluated[s]]},
            string -> rhs], {1}]

The level specification Replaceis not there to make sure that nothing will happen if rhsit is itself a rule or a list of rules.

In[4]:= f[x] // InputForm
Out[4]= {"a" -> 1, "b" -> 2, "c" -> 3}
+1
source

Source: https://habr.com/ru/post/1786655/


All Articles