Skip to content

Instantly share code, notes, and snippets.

@lshifr
Created November 7, 2014 20:14
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 lshifr/ea6f39a3cfaf901b79e8 to your computer and use it in GitHub Desktop.
Save lshifr/ea6f39a3cfaf901b79e8 to your computer and use it in GitHub Desktop.
Smart Let in Mathematica
ClearAll[Let, let, symbolOrListQ, inSetDelayed];
SetAttributes[{Let, let, symbolOrListQ}, HoldAll];
symbolOrListQ[_Symbol] = True;
symbolOrListQ[{___?symbolOrListQ}] = True;
symbolOrListQ[_] = False;
Let::lvset = "Local variable specification `1` is not valid.";
Let /: Verbatim[SetDelayed][lhs_, rhs : HoldPattern[Let[args__, _]]] :=
Module[{result},
Block[{With, inSetDelayed = True},
Attributes[With] = {HoldAll};
result = rhs /. HoldPattern[With[{}, b_]] :> b;
If[result =!= $Failed,
lhs := Evaluate[result]
]
];
If[(Hold[result] /. OwnValues[result]) === Hold[$Failed],
Message[Let::lvset, HoldForm[{args}]]
];
result
];
Let[args___, body_] :=
Block[{result = Catch[let[args, body], let]},
result /; result =!= $Failed
];
Let[args___, _] :=
(
If[! TrueQ[inSetDelayed], Message[Let::lvset, Hold[{args}]]];
$Failed
);
let[args : HoldPattern[Set[_?symbolOrListQ, _] ...], body_] :=
let[{args}, body, {}, {}];
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, {}, {}]]]
];
let[___] := Throw[$Failed, let];
SetAttributes[partThread, HoldAll];
partThread[l___, rhs_] :=
Join @@ Replace[
MapIndexed[Append[#, First@#2] &, Thread[Hold[{l}]]],
Hold[s_, i_] :> Hold[s = rhs[[i]]], {1}];
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment