How to redefine a function in Mathematica by appending to it?
When doing calculations in Mathematica I often need to redefine a function by appending to it. For example if I define
f[n_] := n^2 + n + 1
then after some time I'd like to add 2n^3 so from now on
f[n] = 2n^3 + n^2 + n + 1.
Then I'd like to add Sin[n] and going further
f[n] = 2n^3 + n^2 + n + 1 + Sin[n].
And so o开发者_StackOverflow中文版n.
It's easy to do with variables, for example x += 2. Is there something similar for functions?…
Edited to add – yes, I was doing that to semi-manually find a function that fits data the best. I know there are functions to do that but I wanted to see if I can get there myself. I did that but the way was not elegant so that prompted this question.
You can define a list of your basis functions and then just pick up needed number of elements:
fList = {n^2, n, 1, 2 n^3, Sin[n]};
f[n_] = Total[Take[fList, 3]]
f[n_] = Total[Take[fList, 4]]
f[n_] = Total[Take[fList, 5]]
(*
=> 1 + n + n^2
=> 1 + n + n^2 + 2 n^3
=> 1 + n + n^2 + 2 n^3 + Sin[n]
*)
A late-to-the-party solution: the code below uses an auxiliary function, and to add a term for all subsequent uses, you just have to call a function once, with a second parameter being a pure function expressing the term you want to add:
ClearAll[f];
Module[{g},
g[n_] := n^2 + n + 1;
f[n_, add_: Automatic] /; add === Automatic := g[n];
f[n_, add_: Automatic] := Block[{m}, g[m] = g[m] + add[m]; g[n]];
]
Examples of use:
In[43]:= f[m]
Out[43]= 1 + m + m^2
In[44]:= f[m, 2 #^3 &]
Out[44]= 1 + m + m^2 + 2 m^3
In[45]:= f[m]
Out[45]= 1 + m + m^2 + 2 m^3
In[46]:= f[m, Sin]
Out[46]= 1 + m + m^2 + 2 m^3 + Sin[m]
In[47]:= f[m]
Out[47]= 1 + m + m^2 + 2 m^3 + Sin[m]
With this approach, you should be careful though to call the two-argument form only once, when you want to add the term to the function - or it will be added every time you call.
There are many subtleties craving under your question. Monster subtleties, I mean.
I'll not enter the meander, but you may do something like:
f[n] = n^2;
f[n] = f[n] + 2
(* but for evaluation *)
f[n] /. n -> 2
So, for example for plotting this:
Plot[f[n] /. n -> x, {x, 0, 1}, AxesOrigin -> {0, 0},
PlotLabel -> Framed@f[n]]
However, you should NOT do this. Read more about delayed definition!
It really depends why you need to redefine your function f
. If the reason is that you realised the previous definition was wrong, then by all means just go back to the cell in question, edit it and re-evaluate it to re-define f
.
f[n_] := n^2 + n + 1
Becomes
f[n_] := 2n^3 + n^2 + n + 1
Note the :=
syntax and the underscore.
If, instead, you want f
to take the first definition for, say n<=100
and the second for n>100
, you would use the Condition syntax /;
, as shown below.
f[n_] := n^2 + n + 1 /; n<=100
f[n_] := 2n^3 + n^2 + n + 1 /; n>100
This works, but requires separate functions. Generalising the append function is not so easy.
Clear[f]
AppendToFunction := (
a = DownValues[f];
b = Append[a[[1, 2]], 2 n^3];
f[n_] = Evaluate[b]);
AppendSinToFunction := (
a = DownValues[f];
b = Append[a[[1, 2]], Sin[n]];
f[n_] = Evaluate[b]);
f[n_] := n^2 + n + 1;
f[3] == 9 + 4
DownValues[f]
(*
->True
->{HoldPattern[f[n_]]:>n^2+n+1}
*)
AppendToFunction
f[3] == 9 + 4 + 54
DownValues[f]
(*
->1+n+n^2+2 n^3
->True
->{HoldPattern[f[n_]]:>1+n+n^2+2 n^3}
*)
AppendSinToFunction
f[3] == 9 + 4 + 54 + Sin[3]
DownValues[f]
(*
->1+n+n^2+2 n^3+Sin[n]
->True
->{HoldPattern[f[n_]]:>1+n+n^2+2 n^3+Sin[n]}
*)
精彩评论