MathGroup Archive 2008

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

Search the Archive

Re: A version of With that binds variables sequentially

  • To: mathgroup at smc.vnet.net
  • Subject: [mg94574] Re: A version of With that binds variables sequentially
  • From: dh <dh at metrohm.com>
  • Date: Tue, 16 Dec 2008 06:04:07 -0500 (EST)
  • References: <gi5jof$prg$1@smc.vnet.net>


Hi,

"With" only allowes local constants. "Module" not only allowes local 

constants, but also local variables. This easily solves your problem:

Module[{a1=5,a2,a3},a2=f[a1];a3=g[a1,a2];h[a1,a2,a3]]

hope this helps, Daniel



D. Grady wrote:

> Many times when I'm programming, I write code like this:

> 

> With[{a1 = 5},

>  With[{a2 = f[a1]},

>   With[{a3 = g[a1, a2]},

>    h[a1, a2, a3]]]]

> 

> I wish I could write this instead:

> 

> With[{

>   a1 = 5,

>   a2 = f[a1],

>   a3 = g[a1, a2]},

>  h[a1, a2, a3]]

> 

> Although With doesn't work this way, I didn't see any reason that it

> shouldn't, so I wrote a function called WithMany.  It works by taking

> something in the second form above and holding all of the arguments,

> expanding out to the first form, and then releasing the hold.

> 

> In spite of the simplicity of the idea, it was tricky for me to figure

> out the details of this function.  I thought that someone else might

> find it helpful, and I also had some questions about it.

> 

> Am I using a bad idiom with the nested With's?  Is it better to just

> use Module and be done with it?

> 

> Is there a way to get syntax highlighting for WithMany?  I found the

> SyntaxInformation stuff, but it doesn't seem to expose the

> highlighting that's used for With, Module, or Block.

> 

> Are there any cases where this function fails or does something

> unexpected?

> 

> Is there a clearer way to write this function?  It seems very

> complicated right now, especially in the fact that I need to use both

> a special symbol with attribute HoldAll and a special function with

> attribute HoldAll.  Maybe someone sees a way to make it simpler?

> 

> Really I'm just curious what other people think about this.  Any

> comments would be appreciated.

> 

> A simple example:

> 

> WithMany[{

>   a1 = 5,

>   a2 = RandomChoice@Range@a1,

>   a3 = f[a2, a1]},

>  {a1, a2, a3}]

> 

> {5, 1, f[1, 5]}

> 

> The definition:

> 

> ClearAll[WithMany];

> SetAttributes[WithMany, HoldAll];

> WithMany[args_, body_] :=

>  Module[{heldArgs, f, W, structure},

>   (* The very first thing that has to happen is to put args into a

> function with a hold attribute like HoldAll.  Doing anything else

> means that args will be evaluated. *)

> 

>   heldArgs = Hold[args];

> 

>   (* args is coming to us as a list of bindings.  We want to replace

> the List with Hold.  We can do this because Hold is wrapping

> everything right now. *)

> 

>   heldArgs = Apply[Hold, heldArgs, {1}];

> 

>   (* Now we want to take the outermost Hold away so that we're left

> with Hold[bind1,bind2,bind3,...]. *)

>   heldArgs = ReleaseHold[heldArgs];

> 

>   (* Now we want to put each binding inside a List because With

> requires that syntax. *)

>   heldArgs = Map[List, heldArgs];

> 

>   (* Set up a symbol that will serve as a non-evaluating wrapper. *)

> 

>   SetAttributes[W, HoldAll];

> 

>   (* Next define a function to use in the Fold operation.  This

> function needs to have the attribute HoldAll, otherwise it will

> evaluate its arguments prematurely. *)

>   f = Function[

>     {bod, binding},

>     W[binding, bod],

>     {HoldAll}];

> 

>   (* Use f to Fold W onto the bindings.  This will create the correct

> structure without evaluating anything. *)

> 

>   (* If we had used With directly instead of W, then as soon as the

> first With statement is completely formed it will be evaluated,

> leaving the more outer With statements useless. *)

> 

>   (* Wrapping body in Unevaluated is neccessary to prevent body from

> being evaluated as soon as it appears in the arguments of Fold. *)

> 

>   structure = Fold[f, Unevaluated[body], Reverse@heldArgs];

> 

>   (* The final step is to replace all of the W symbols with With.

> Replacement still works inside of Hold, and the symbol W is local to

> this module so there's no danger of messing up the input. *)

>   structure /. W -> With

>   ]

> 




  • Prev by Date: Re: Calculate the first time, not each time (?)
  • Next by Date: Re: Calculate the first time, not each time (?)
  • Previous by thread: A version of With that binds variables sequentially
  • Next by thread: Re: A version of With that binds variables sequentially