Re: How to "soft-code" a Block?
- To: mathgroup at smc.vnet.net
- Subject: [mg113354] Re: How to "soft-code" a Block?
- From: Leonid Shifrin <lshifr at gmail.com>
- Date: Mon, 25 Oct 2010 06:39:47 -0400 (EDT)
Hi Daniel,
Your first attempt can be modified to work:
Unevaluated[Block[vals,expr]]/.OwnValues[vals]
gives a result equivalent to the hard-coded block. Your suggestion with
rules looks too complex to me in this context (I used a similar construct
but in very different situations). The way to make a really simple run-time
Block would be to wrap your declaration list in Hold:
heldvals = Hold[{a=b,c=3,b=c}];
Now, the following simple function will work:
ClearAll[runtimeBlock];
SetAttributes[runtimeBlock,HoldRest];
runtimeBlock[Hold[vars_List],body]:=Block[vars,body];
You use it as
runtimeBlock[heldvals,{a,b,c}]
or
expr = {a,b,c}
runtimeBlock[heldvals,expr]
Alternatively, the following will also work:
Block@@Append[heldvals,Unevaluated[expr]]
While I checked the results on a different PC, I typed this manually here,
so there
could be some typos.
Hope this helps.
Regards,
Leonid
On Sat, Oct 23, 2010 at 7:03 AM, dr DanW <dmaxwarren at gmail.com> 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
>
>
>