MathGroup Archive 2008

[Date Index] [Thread Index] [Author Index]

Search the Archive

Re: Assigning multiple variables within a Block[] statement (e.g.

  • To: mathgroup at smc.vnet.net
  • Subject: [mg88323] Re: Assigning multiple variables within a Block[] statement (e.g.
  • From: Albert Retey <awnl at arcor.net>
  • Date: Thu, 1 May 2008 06:28:13 -0400 (EDT)
  • References: <fv9jsm$50f$1@smc.vnet.net>

Hi,

> What I'm trying to do:
> I have a list of parameters that I am using across several functions.  I am 
> trying to come up with a good way to avoid copying/pasting these parameter 
> assignments everywhere.  Here is an example code that sort of accomplishes 
> this goal: (Suppose my parameters are a,b, and c)
> 
> paramlist = {a -> 1, b -> 4, c -> 8};
> paramlistnames = First /@ paramlist;
> 
> foobar2[x_] := Block[Evaluate[Flatten[{paramlistnames, {d, e, f}}]],
> {a, b, c} = paramlistnames /. paramlist;
> {d,e,f} = {1,1,1};
> x*a*b*c*d*e*f
> ]
> 
> The line
> {a, b, c} = paramlistnames /. paramlist;
> effectively sets a, b, and c to their values, at which point I can proceed 
> with the rest of the function.
> 
> Questions:
> 1. Is this the most effective way to accomplish the task at hand?  If no, 
> what is?

I think you are fooling yourself. Using Block (or Module) mainly serves
the purpose of scoping, which doesn't work if you do it this way. To see
what I mean evaluate the following:

foobar2[5]
a=2
foobar2[5]

You need to be more careful about evaluation when doing this. One
possibility would be:

foobar3[x_] := Block @@ Join[
   Replace[Hold[Evaluate@Join[
       Flatten[
        Extract[OwnValues[paramlistnames], {1, 2}, Hold] /.
         List -> Hold],
       Hold[d, e, f]
       ]], Hold -> List, {2}, Heads -> True],
   Hold[
    {a, b, c} = List @@ paramlistnames /. List @@ paramlist;
    {d, e, f} = {1, 1, 1};
    x*a*b*c*d*e*f
    ]
   ]

As you can note, there is extra effort necessary to avoid early
evaluation. Maybe this can be done more elegant than what I have come up
with. Note that you need to access the ownvalue of paramlistnames
directly to avoid early evaluation of the parameternames and you have to
take care to define your parameters before any of their names get any
definition. This can be avoided by e.g. wrapping your parameterlist with
Hold instead of List, which also can make the later handling easier.

However you achieve to avoid early evaluation at the various stages, you
might want to define something like:

SetAttributes[ParameterBlock, HoldRest]

ParameterBlock[params_, {vardefs___}, body_] := Apply[
  Block,
  Join[
   Replace[
    Hold[Evaluate@Join[params /. Rule -> Set, Hold[vardefs]]],
    Hold -> List, {2}, Heads -> True
    ],
   Hold[body]
   ]
  ]

which will make possible to define your parameters and functions as e.g.:

$parameter = Hold[a -> 1, b -> 4, c -> 8]

foobar4[x_] := ParameterBlock[$parameter, {d = 1, e = 1, f},
  f = 1;
  x*a*b*c*d*e*f
  ]

> 2. Note that I still have to explicitly use {a, b, c} = paramlistnames /. 
> paramlist; something like Hold[paramlistnames] =  paramlistnames /. 
> paramlist; results in an error message.  Is there a way to do the assignment 
> but use the "paramlistnames" somehow so that I don't have to name the 
> variables explicitly?

the above definition of ParameterBlock solves this, too.  If you want to
 understand what it does it is best to replace the Block with Hold, then
you will see the (held) expression which Block is applied to and can
check that it basically is what you want (I think you want) it to be...

A last remark: you probably should look into how Options work for
Mathematica functions, which is the standard way of handling what seems
to be part of your problem...

hth,

albert


  • Prev by Date: ExtraAxes for Plot[]
  • Next by Date: Bilateral cell problem w/ Manipulate
  • Previous by thread: Re: Assigning multiple variables within a Block[] statement (e.g.
  • Next by thread: Re: diff equation