Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

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.

share|improve this question

1 Answer 1

up vote 14 down vote accepted

Perhaps something like this:

SetAttributes[localSet, HoldAll]

localSet[lhs_, rhs_] := 
  Union @@ Cases[
    Unevaluated[lhs], 
    Verbatim[Pattern][p_, _] :> HoldComplete[p],
    Infinity,
    Heads -> True
  ] /. _[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}
share|improve this answer
    
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. –  Szabolcs Feb 19 '12 at 9:40
2  
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. –  Szabolcs Feb 19 '12 at 12:12
1  
+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. –  Leonid Shifrin Feb 19 '12 at 13:54
1  
@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. –  Leonid Shifrin Feb 19 '12 at 20:56
1  
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 '13 at 17:24

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.