Skip to content

Instantly share code, notes, and snippets.

@teake
Created November 7, 2014 19:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save teake/d914c07f18e89094efa1 to your computer and use it in GitHub Desktop.
Save teake/d914c07f18e89094efa1 to your computer and use it in GitHub Desktop.
Mathematica Let scoping construct
ClearAll[Let, let, symbolOrListQ];
SetAttributes[{Let, let, symbolOrListQ}, HoldAll];
Let::lvset = "Local variable specification `1` is not valid.";
Let /: Verbatim[SetDelayed][lhs_, rhs : HoldPattern[Let[__, _]]] :=
Block[{With}, Attributes[With] = {HoldAll};
lhs := Evaluate[rhs /. HoldPattern[With[{}, b_]] :> b]];
Let[args : HoldPattern[Set[_?symbolOrListQ, _] ...], body_] :=
let[{args}, body, {}, {}];
Let[args___, _] /; Message[Let::lvset, HoldForm@{args}] = Null;
symbolOrListQ[_Symbol] = True;
symbolOrListQ[{___?symbolOrListQ}] = True;
symbolOrListQ[_] = False;
let[{}, body_, {}, _] := With[{}, body];
let[{Set[{s___}, rhs_], rest___}, body_, dec_, syms_] :=
Module[{temp},
partThread[s, temp] /.
Hold[d___] :> let[{temp = rhs, d, rest}, body, dec, syms]];
let[{Set[sym_, rhs_], rest___}, body_, {decs___}, {syms___}] /;
FreeQ[Unevaluated[rhs], Alternatives[syms]] :=
let[{rest}, body, {decs, sym = rhs}, {syms, HoldPattern[sym]}];
let[{args___}, body_, {decs__}, _] :=
Block[{With}, Attributes[With] = {HoldAll};
With[{decs}, Evaluate[let[{args}, body, {}, {}]]]];
SetAttributes[partThread, HoldAll];
partThread[l___, rhs_] :=
Join @@ Replace[
MapIndexed[Append[#, First@#2] &, Thread[Hold[{l}]]],
Hold[s_, i_] :> Hold[s = rhs[[i]]], {1}];
ClearAll[f]
f[x_Integer] :=
Let[z@range = Range[2] + x, {a, b} = range, c = g[range],
h[a, b, c]];
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment