# How to make a function like Set, but with a Block construct for the pattern names

How can we define a function that works like f[x_]=ComputeSomething[x] and treats x as a variable that does not have a value? We could call this function LocalSet and the computation should be done when the assignment is made as in the following example.

var=3;
LocalSet[f[var_],Normal[Series[Exp[var],{var,0,3}]]];
DownValues[f]

(*
---> {HoldPattern[f[var_]]:>1+var+var^2/2+var^3/6}
*)

var
(*
---> 3
*)


Notice I don't want to be limited to a pattern variable (x_). The function called LocalSet should figure out what symbols are used for patterns and evalute the right side with those variables in a Block construct.

Perhaps something like this:

SetAttributes[localSet, HoldAll]

localSet[lhs_, rhs_] :=
Union @@ Cases[
Unevaluated[lhs],
Verbatim[Pattern][p_, _] :> HoldComplete[p],
Infinity,
] /. _[x___] :> Block[{x}, lhs = rhs;]


Test:

var=3;
localSet[f[var_],Normal[Series[Exp[var],{var,0,3}]]]
DownValues[f]

{HoldPattern[f[var_]] :> 1 + var + var^2/2 + var^3/6}

• I came up with almost exactly the same code. Hope you don't mind my edit to make it work in more general cases and avoid returning a value. Feb 19, 2012 at 9:40
• It not only about returning a value. It's about evaluating the expression, which might have side effects or unintended consequences. Consider f[x_?NumericQ] := (Print["numeric"]; x); n = 5; localSet[g[n_], f[n]], which has different behaviour when the semicolon is omitted. I think it's important here that the expression not be evaluated with n having a value---there's no telling what that might lead to. Feb 19, 2012 at 12:12
• +1. I would write the same code, except including Heads->True option in Cases, if you want to cover SubValues. Right now an attempt to assign to say f[var_][1] will produce an error. If you want to be totally safe, I'd also use HoldComplete in place of Hold. Feb 19, 2012 at 13:54
• @Mr.Wizard The possible troublesome symbols will be deeper than level one during the call to localSet[f[...],rhs], because they will be inside f. So, as long as localSet is HoldAll, you don't have to care about them, exactly due to the depth-1 limitation for UpValues search. But when you destructure, you have Hold[sym], and here HoldComplete is essential. Feb 19, 2012 at 20:56
• Well, to make it a little bit moore robust it would be better to use a preorder ReplaceAll based Cases that stops inside Verbatims. Something along the lines of Module[{tag},Reap[Unevaluated[lhs]/.{i_Verbatim:>i, Verbatim[Pattern][p_, _]/;Sow[HoldComplete[p], tag]:>Null}, tag][[1, -1]]]
– Rojo
Jul 19, 2013 at 17:24