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