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_] = ...
-
5$\begingroup$ The documentation contains a tutorial dedicated to explaining the difference. $\endgroup$– Simon WoodsCommented Jul 29, 2012 at 13:28
-
2$\begingroup$ I discuss that in great detail here. $\endgroup$– Ted ErsekCommented Jul 29, 2012 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.
-
$\begingroup$ for being clear
y[x_]=
: it is like one time functiony[x_]:=
it is like normal funtion ?? $\endgroup$– DSaadCommented Jul 29, 2012 at 13:17 -
3$\begingroup$ +1 but please include the names
Set
andSetDelayed
in your answer, for reference and easy searching. $\endgroup$ Commented Jul 29, 2012 at 13:19 -
$\begingroup$ Is there a difference then between y[x_]= and y[x_]:=y[x]= for caching values ? $\endgroup$– faysouCommented Jul 29, 2012 at 13:53
-
2$\begingroup$ @DSaad, no, take what acl said more literally.
y[x_]=rhs
means "evaluate the rhs to get the expression of the FUNCTION", whiley[x_]:=rhs
means that rhs is literally the expression of the function $\endgroup$– RojoCommented Jul 29, 2012 at 14:37 -
$\begingroup$ @FaysalAberkane definately.
y[x_]=
doesn't cache any values at all $\endgroup$– RojoCommented Jul 29, 2012 at 14:39
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).