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 13 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
    
@Leonid, thank you, I will add Heads -> True. Regarding HoldComplete I hesitate to use it unless I know it is needed because there are times it is not wanted. If you have a different opinion you know I would like to hear it. –  Mr.Wizard Feb 19 '12 at 14:04
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

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.