One of the things that bothers me about the built-in scoping constructs is that they evaluate all of the local variable definitions at once, so you can't write for example
With[{a = 5, b = 2 * a},
...
]
So a while ago I came up with a macro called WithNest that allows you to do this. I find it handy, since it lets you keep variable bindings local without having to do something like
Module[{a = 5,b},
b = 2 * a;
...
]
In the end, the best way I could find to do this was by using a special symbol to make it easier to recurse over the list of bindings, and I put the definition into its own package to keep this symbol hidden. Maybe someone has a simpler solution to this problem?
If you want to try it out, put the following into a file called Scoping.m
:
BeginPackage["Scoping`"];
WithNest::usage=
"WithNest[{var1=val1,var2=val2,...},body] works just like With, except that
values are evaluated in order and later values have access to earlier ones.
For example, val2 can use var1 in its definition.";
Begin["`Private`"];
(* Set up a custom symbol that works just like Hold. *)
SetAttributes[WithNestHold,HoldAll];
(* The user-facing call. Give a list of bindings and a body that's not
our custom symbol, and we start a recursive call by using the custom
symbol. *)
WithNest[bindings_List,body:Except[_WithNestHold]]:=
WithNest[bindings,WithNestHold[body]];
(* Base case of recursive definition *)
WithNest[{},WithNestHold[body_]]:=body;
WithNest[{bindings___,a_},WithNestHold[body_]]:=
WithNest[
{bindings},
WithNestHold[With[List@a,body]]];
SyntaxInformation[WithNest]={"ArgumentsPattern"->{{__},_}};
SetAttributes[WithNest,{HoldAll,Protected}];
End[];
EndPackage[];