6
$\begingroup$

Background: there are many, many questions here about the infamous ::setraw error. More often, than not, they have to do with repeated assignments to symbols.

Here's the code:

ls = {a, b, c};
Evaluate[ls] = {1, 2, 3};

This command will work only once. It got me thinking, how, once a, b, and c already have OwnValues, would one go about reassigning them, by using only the symbol ls and not referencing a, b, or c directly?

What about injecting them into Block, Module and related?

Of course, all sorts of combinations of OwnValues, Hold, etc, that came to my mind, at one point or another need an Evaluate or similar at some point, but Evaluate immediately drills down to {1, 2, 3}.

I post one approach that seems to work as a self-answer, but it feels rather hackish. I'm pretty sure, there are better ways to go about this.

$\endgroup$
6
  • 2
    $\begingroup$ One relatively simple way is to use injector pattern: Hold[ls]/.OwnValues[ls]/.Hold[res_]:>(res = {1,2,3}). More generally, one can do Unevaluated[code]/.OwnValues[sym], in this case it will be Unevaluated[ls = {1,2,3}] /. OwnValues[ls]. This form will be easy to generalize to several symbols in need of partial evaluation. $\endgroup$ Mar 2 '16 at 15:47
  • $\begingroup$ @LeonidShifrin The first time this question struck me, was when I wanted to do something like Block[Join[list1,list2], code], but I see now, that this would drastically shift the goalposts. Maybe, when I encounter this use case again, I'll ask a new question. The injector pattern is much simpler than I thought, though, thanks. $\endgroup$
    – LLlAMnYP
    Mar 2 '16 at 16:10
  • $\begingroup$ PS I just know there're extensive threads here on evaluation control, that are very relevant. If anyone recalls them, they ought to be linked. $\endgroup$
    – LLlAMnYP
    Mar 2 '16 at 16:13
  • 1
    $\begingroup$ The Block thing can also be done relatively easily. If you pass them directly, thin something like this: ClearAll[block]; SetAttributes[block, HoldAll];block[symlists : {__Symbol} ..., code_] := Join @@ Apply[Hold, Unevaluated[{symlists}], {1}] /. Hold[syms___] :> Block[{syms}, code];. Example: {x, y, z, t} = {1, 1, 1, 1}; block[{x, y}, {z, t}, Print[x, y, z, t]]. If you store them in variables, add an extra step like the one I described above. $\endgroup$ Mar 2 '16 at 16:32
  • $\begingroup$ @Leo Neat. But also demonstrates, that there'll need to be a very specific injector-pattern-thing for every different use case. Still, that's more than enough examples to work off. $\endgroup$
    – LLlAMnYP
    Mar 2 '16 at 16:42
1
$\begingroup$

My MWE involves using Mr. Wizards step function:

SetAttributes[step, HoldAll]

step[expr_] :=
  Module[{P},
    P = (P = Return[#, TraceScan] &) &;
    TraceScan[P, expr, TraceDepth -> 1]
  ]

and some hackish nonsense

Internal`InheritedBlock[{Set},
  ClearAttributes[Set, SequenceHold]; 
  With[{HoldForm = Sequence},
    # = {4, 5, 6}] &@step[ls]
]

which survives, thanks to Set's attribute of HoldFirst. When I have the need to modify so many built-ins, I begin to feel uncomfortable.

$\endgroup$

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.