Re: How to "soft-code" a Block?

*To*: mathgroup at smc.vnet.net*Subject*: [mg113720] Re: How to "soft-code" a Block?*From*: Daniel Huber <dh at metrohm.com>*Date*: Tue, 9 Nov 2010 03:52:11 -0500 (EST)*References*: <i9ufef$rej$1@smc.vnet.net>

On 23.10.2010 13:03, dr DanW wrote: > Hard coding a Block is easy: > In[1]:= Block[{a = b, b = c, c = 3}, > {a, b, c} > ] > > Out[1]= {3, 3, 3} > > But what if my variable list and expression are themselves values, as > in: > In[1]:= vals = {a = b, c = 3, b = c}; > expr = {a, b, c}; > Block[vals, expr] > > During evaluation of In[1]:= Block::lvlist: Local variable > specification vals is not a List.>> > > Out[3]= Block[vals, expr] > > Which fails for many obvious reasons. However, is there a way to do > this, as in: > > In[1]:= vals = {a -> b, c -> 3, b -> c}; > expr = {a, b, c}; > RuleBlock[vals, expr] > > Out[3]= {3, 3, 3} > > How can I write RuleBlock[], which functions as a scoping construct > and Set's the left hand sides to the right hand sides of all the Rules > in the list? > > Why do I need this? I am writing a modeling program which builds up a > complicated compound expression in terms of some parameters. The > expression can be evaluated quickly once numerical values of the > parameters are supplied. I also want to be able to evaluate the > expression for different sets of parameters. > > The obvious solution, using expr //. vals, does not always work for > several reasons: > > * The expression contains several SparseArray's, and Replace does not > work within SparseArray's. > * The expression may contain other scoping structures or functions > which do not respond to Replace unless wrapped with Evaluate every > place it is used > * This is a complicated, programmatically generated expression, and > finding every instance where Replace would have to be Evaluate'd would > be tedious (meaning: error prone) > > This would be so much easier with a scoping structure I could soft- > code. I have attempted this with: > > RuleBlock[r_?OptionQ, exp_] := > Block[ > Evaluate[r[[All, 1]]], > Evaluate[r /. Rule -> Set]; > exp > ]]; > > Which seems to work most of the time, but has failed me for reasons > that I cannot explain on some occasions. I can't come up with a > simple example that demonstrates this failure. > > Whenever I work this hard on something this low-level in Mathematica, > it usually means that there is an obvious solution I missed, or a > feature in Mathematica I am unaware of. I have struggled with this > one for many years and have used various band-aids, but I am tired of > it and want to have a robust solution that works all the time. > > Any suggestions? > > Regards, > Daniel > > Hi Daniel, look at the following code: CreateBlock[lvals_, rvals_, expr_] := Module[{v, myBlock}, v = Thread[mySet[lvals, rvals]]; SetAttributes[myBlock, HoldAll]; myBlock[vals, expr ] /. vals -> v /. mySet -> Set /. myBlock -> Block ] CreateBlock[{a, b, c}, {b, c, 3}, {a, b, c}] /. myBlock -> Block We first create a Block that can not evaluate by giving it an arbitrary Head "myBlock" and the attribute HoldAll. We must further prevent Set from evaluating by using an arbitrary name "mySet". With this preparation we can set up "myBlock". Having done so, we change "mySet" to "Set" and "myBlock" to "Block". By the way, why are you using Block and not Module? Do you really want to use dynamic scoping? cheers Daniel Huber