Put local variables for Block in a variable

6

2

Is is possible to assign {x = 2, y = 3, z = 4} to a variable var so that one can write

Block[var, x*y*z]

(or similar) instead of

Block[{x = 2, y = 3, z = 4}, x*y*z]

?

st12

Posted 2013-04-25T19:59:17.237

Reputation: 581

Almost a duplicate: (19758)

– Mr.Wizard – 2019-11-08T08:52:36.400

If I remember right, I think there is a similar question with an excellent answer by @LeonidShifrin . Just can't recall the keywords right now.. – Silvia – 2013-04-25T20:11:24.860

1

@Silvia I answered a similar one here - perhaps, that's what you meant? One of the solutions I posed does use the injector pattern, although by that time it did not yet have this nice name :-)

– Leonid Shifrin – 2013-04-25T20:21:09.770

@LeonidShifrin It's this one I meant, looks like a bad memory, alerts me to go to sleep now :/

– Silvia – 2013-04-25T20:24:59.580

While this is a simpler question than the linked duplicate as it does not start with strings, it is a subset of that question and also answered there. If anyone feels that this should not be closed please vote accordingly or respond to this comment. – Mr.Wizard – 2013-04-26T02:04:02.773

@Leonid long overdue, but I finally referenced that answer in my own. At the time of writing I did not recall your use.

– Mr.Wizard – 2013-04-26T02:29:54.390

@Mr.Wizard Thanks, I do appreciate that, but I think you are responsible for really bringing this to widespread use, so it really does not matter that it was used in some answers before yours. In your answer, this was a central thing, and the question was asked specifically about it, while in other answers it was a technical trick to get something else working, and was just one of possible solutions there. – Leonid Shifrin – 2013-04-26T08:51:37.000

@Mr.Wizard I think the question is stated more clearly here and I think the answers here add something, but if you put Ajasja's observation in your answer I'd be happy :). – Jacob Akkerboom – 2013-04-26T11:11:48.383

@Jacob Pardon me, which observation? – Mr.Wizard – 2013-04-26T17:20:21.087

@Mr.Wizard I'm sorry I'll have to change my opinion (and add that it is of course humble). I don't like the examples with MapIndexed in a question that is supposed to more general than this one. Arf I'm stressed don't listen to me :) – Jacob Akkerboom – 2013-04-26T17:45:54.340

Answers

6

This could be another case for the injector pattern:

var = Hold@{x = 2, y = 3, z = 4}

var /. Hold[inj_] :> Block[inj, x*y*z]

(*24*)
?x
(*Global`x --- so we did not leak*)

Ajasja

Posted 2013-04-25T19:59:17.237

Reputation: 13 114

4

Here's something I found:

With[{h := {x = 7, y = 8}},
 Block[h, x y]]

56

amr

Posted 2013-04-25T19:59:17.237

Reputation: 5 317

2That's an excellent application of this AFAIK-undocumented syntax. My old "injector pattern" answer was given specifically to handle cases where this method did not work (Sequence); in cases where it does it's surely easier to read for those not already acquainted with the "injector" or deeply familiar with replacement rules. +1 – Mr.Wizard – 2013-04-26T02:07:33.807

2It should be noted that this does not use var but the Set expressions explicitly. Nevertheless it is instructive and my +1 stands. – Mr.Wizard – 2013-04-26T02:17:43.937

2

The way I prefer is

var := {x = 2, y = 3, z = 4}
ReleaseHold[Hold[Block[var, x*y*z]] /. OwnValues[var]]
x

-> 24

-> x

Or

Apply[Block, Hold[var, x*y*z] /. OwnValues[var]]
x

-> 24

-> x

For

hVars = Hold[{x = 2, y = 3, z = 4}];

We can do

ReleaseHold[Hold[Block][hVars, Hold[x*y*z]]]
x

-> 24

-> x

Jacob Akkerboom

Posted 2013-04-25T19:59:17.237

Reputation: 11 718

2

var /: Block[var, code_] := Block[{x = 2, y = 3, z = 4}, code]

So

x = 100;
Block[var, x + 2]

(* 4 *)

Rojo

Posted 2013-04-25T19:59:17.237

Reputation: 40 993