# How to block list of variable that is of string form?

For example, I have

varList={"a1","a2",...}


a1, a2,... are all variables, they maybe assigned values already.

What I want to do is temporarily Block all variables in varList for a segment of my code. This means equivalent to Block[{a1,a2,...},other code].

So maybe a function myBlock similar to Block,

myBlock[varList,other code]


How to do this?

myBlock // ClearAll

myBlock // Attributes = {HoldAll};

(*for a standardBlock syntax *)
myBlock[varList : {(_Symbol | _Set) ..}, code_] := Block[varList, code]

(*for string spec hidden in a symbol *)
myBlock[varList_Symbol, code_] /; ValueQ[varList] := myBlock[Evaluate@varList, code]

(* for list of string specs*)
myBlock[varList : {__String}, code_] :=
Join @@ ToExpression[varList, StandardForm, Hold] /.
Hold[vars__] :> Block[{vars}, code]


a1 = 1

{ myBlock[{"a1"}, a1 = 2; a1], a1 }

{ myBlock[{a1}, a1 = 3; a1]  , a1 }

{ myBlock[{a1 = 4}, a1]      , a1 }

{ myList = {"a1"}
; myBlock[myList, a1 = 5; a1], a1 }

{ myList = {"a1 = 6", "a2"}
; myBlock[myList, a1]        , a1 }


1

{2,1}

{3,1}

{4,1}

{5,1}

{6,1}

• You could make use of the Listable attribute of ToExpression, e.g., ToExpression[varList,StandardForm,Hold] – Carl Woll Jan 22 '18 at 18:04
• @CarlWoll +1 sure I could, If I only knew. All those years of mapping ;( – Kuba Jan 22 '18 at 19:02
• Thank you so much! Learned a lot. I took some time rereading Wagner's "power programming...", finally has some progress in understanding Hold stuff(which should be know years ago) , and came out my version as an answer. What is more, I actually struggled to construct a function let's call it convert, so that Block[Evaluate@convert@varList,code] will work. But I failed, so I thought maybe it is not possible for such convert function, what do you think? : ) – matheorem Jan 23 '18 at 8:09
• @Kuba Oh, there is also string mix symbol case missing, though rare, but... – matheorem Jan 23 '18 at 8:42
• @Kuba I updated a unified version. Now it is fully settled down :) – matheorem Jan 23 '18 at 14:37

This answer is enlightened by Kuba. Thanks.

update

By utilizing RowBox and the fact that ToString doesn't change string. I provide a unified version of myBlock with a single definition that is fully compatible with built-in Block, and at the same time support list of symbols in string form or a list of mixture of symbol and string form(currently not supported by Kuba's version).

ClearAll[myBlock];
SetAttributes[myBlock, HoldAll];
myBlock[varList_, code_] :=
Module[{toStringWithHold, varStringList, holdVars},
toStringWithHold = Function[x, ToString[Unevaluated[x]], {HoldAll}];
varStringList = toStringWithHold /@ Unevaluated[varList];
varStringList =
Flatten@StringSplit[Riffle[varStringList, ","], "=" -> "="];
holdVars =
ToExpression[RowBox@Prepend[Append[varStringList, "}"], "{"],
StandardForm, Hold];
holdVars /. Hold[x_] :> Block[x, code]];


It uses RowBox technique, also thanks to Kuba

So now take a look at below

a1 = 100;
a2 = 200;
{myBlock[{a1, a2}, a1 = 1; a2 = 2; {a1, a2}], {a1, a2}}
{myBlock[{"a1", "a2"}, a1 = 1; a2 = 2; {a1, a2}], {a1, a2}}
{myBlock[{"a1", a2}, a1 = 1; a2 = 2; {a1, a2}], {a1, a2}}
{myBlock[{"a1=1", a2 = 2}, {a1, a2}], {a1, a2}}
{varList = {"a1", "a2"}; myBlock[varList, a1 = 1; a2 = 2; {a1, a2}], {a1, a2}}
{varList = {"a1=1", "a2=2"}; myBlock[varList, {a1, a2}], {a1, a2}}


They all gives

{{1, 2}, {100, 200}}


Which means that myBlock correctly block variables, and doesn't affect global value.