I have a problem with defining a function and most of time I get confused by Set or = and SetDelayed or :=.
I read the help section but I didn't find out what the difference is between defining a function as y[x_] := ... and y[x_] = ...
- 124,525
- 11
- 401
- 574
- 1,173
- 2
- 14
- 19
-
5The documentation contains a tutorial dedicated to explaining the difference. – Simon Woods Jul 29 '12 at 13:28
-
2I discuss that in great detail here. – Ted Ersek Jul 29 '12 at 13:45
2 Answers
References and intro
First, let me point out that = is shorthand for Set and := for SetDelayed; this facilitates searching the docs. Also, as Simon Woods points out in a comment to the question, there is a tutorial on this.
Explanation
The basic distinction is this: y[x_]=expr means evaluate expr, then whenever you see y[something] evaluate evaluate what resulted. On the other hand, y[x_]:=expr means "whenever you see y[something], evaluate expr anew".
Here's how to see it:
a = 5;
y[x_] = a*x
y[3]
a = 10
y[3]
(*
15
10
15
*)
That is, when you define y, it evaluates the right hand side to 5*x and assigns that; if you change a later, it never sees it. On the other hand,
a = 5;
f[x_] := a*x
f[3]
a = 10
f[3]
(*
15
10
30
*)
Compare also:
?? y

So, the value of a at the time of definition has been "baked in", while with SetDelayed, we get
??f

that is, the value of a at execution time is what will be used.
Pitfalls
Here is an example where using SetDelayed results in a calculation being unnecessarily performed multiple times:
fsd[x_] := Integrate[z, {z, 0, x}]
gs[x_] = Integrate[z, {z, 0, x}];
If I try with a number, they give the same answer. But look at the DownValues:
??fsd

??gs

So, in gs, the integration has already been done, while in fsd it is performed anew every time fsd is evaluted. Observe:
t1 = Table[fsd[x], {x, 0, 1, .05}]; // AbsoluteTiming
t2 = Table[gs[x], {x, 0, 1, .05}]; // AbsoluteTiming
(*
{0.061729, Null}
{0.000061, Null}
*)
and t1 == t2 evaluates to True. The reason for the timing differences is precisely that the symbolic integration is done every time for one, only once for the other.
Another possible pitfall is using an already-defined symbold for the right hand side. For instance, consider the difference between these:
ClearAll[f, g];
x = 5;
f[x_] := Sin[x];
g[x_] = Sin[x];
f[1]
g[1]
(*
Sin[1]
Sin[5]
*)
A simple way to avoid this is to simply use a formal symbol:
h[\[FormalX]_] = Sin[\[FormalX]]
which looks like this in the FrontEnd:

Memoization
As a final note, one may combine Set and SetDelayed to implement memoization. Here is how to calculate a Fibonacci number recursively, with
ClearAll[fib];
fib[1] = 1;
fib[2] = 1;
fib[n_Integer] := fib[n] = fib[n - 1] + fib[n - 2]
and without
ClearAll[fibnaive];
fibnaive[1] = 1;
fibnaive[2] = 1;
fibnaive[n_Integer] := fibnaive[n - 1] + fibnaive[n - 2]
memoization. The idea behind this is explained, for instance, here or here. You can also find some elaborations here.
- 235,386
- 17
- 334
- 747
- 19,834
- 3
- 66
- 91
-
for being clear
y[x_]=: it is like one time functiony[x_]:=it is like normal funtion ?? – DSaad Jul 29 '12 at 13:17 -
3+1 but please include the names
SetandSetDelayedin your answer, for reference and easy searching. – Mr.Wizard Jul 29 '12 at 13:19 -
Is there a difference then between y[x_]= and y[x_]:=y[x]= for caching values ? – faysou Jul 29 '12 at 13:53
-
2@DSaad, no, take what acl said more literally.
y[x_]=rhsmeans "evaluate the rhs to get the expression of the FUNCTION", whiley[x_]:=rhsmeans that rhs is literally the expression of the function – Rojo Jul 29 '12 at 14:37 -
-
-
@FaysalAberkane I am not sure I understood, but
y[x_]=Sin[x]re-evaluates (say)Sin[5.]no matter how many times you sayy[5.]. It doesn't cache values at all in this sense, whiley[x_]:=y[x]=Sin[x]remembers thaty[5.]is whatever it is (ie it only evaluatesSin[5.]once). – acl Jul 29 '12 at 15:16 -
-
@Mr.Wizard I was explicitly trying to reduce complexity. As I mentioned nothing about localizing the symbols on the rhs earlier, I do not see how it is consistent to do it in the final section (as you know perfectly well
x = 5; y[x_] = Sin[x]is a dangerous thing to do). But, you are correct: I should point out that the rhs is not localized. – acl Jul 29 '12 at 18:20 -
@Mr.Wizard I added a mention in the pitfalls (as it is indeed a likely tripping point). – acl Jul 29 '12 at 18:28
-
Yes, I'm being grouchy again, but
Clearis about the worst way to localize, asxmight actually be needed for something. Much better to useBlockor Formal Symbols. – Mr.Wizard Jul 29 '12 at 18:33 -
@Mr.Wizard formal symbols it is, then :) in fact I was not familiar with these so thanks for pointing it out (I had seen you use them but had chalked it down to general perversity on your part) – acl Jul 29 '12 at 18:42
-
-
@acl Does this mean that computationally pure functions can always be written with
Setrather thanSetDelayedas long as we use formal symbols in the definition? – Alan Jun 15 '17 at 14:20
Another quick example:
I have a function:
f[x1_,x2_]:= x1+x1*x2
and I want to find it's derivative according to x2 at specific locations of x1 and x2.
m[x1_,x2_] = D[f[x1,x2],x2]
If you use use ":" before the "=", (Set Delay), it evaluates the function when it is needed, hence it will evaluate the function only when values for x1 and x2 are given.
The function definition without ":" before the "=" (Set) evaluates the function before it is used and the output is assigned to m[x1_,x2_], so if you input values in m[x1_,x2_] they are put into the already-differentiated equation.
If now, you would decide to put a ":" in front of the "=" for m[x1_,m2_],it will not work, since one cannot differentiate a function with respect to a numerical value (5 for example).
- 2,510
- 14
- 28