Why did Set work instead of SetDelayed?

I started with the following expression

a[t_] := -Pi Sin(Pi/2*t)


where initial velocity is 2 Pi and initial distance is 1.

and integrated to find v[t]

v[t] := 2 Pi*Cos[pi/2*t]


and integrated one more time to find x[t]

x[t_] := 1 + 4 Sin[Pi/2*t]


When I tried plotting these 3 expressions in one graph I either got an empty plot or got the error message Integrate::ilim.

So I went back and used Set instead, based on this answer and this time it worked. However, I really didn't understand as to why Set worked instead of SetDelayed. Can someone explain to me why Set worked instead of SetDelayed in this context.

• I would guess you should have written v[t_]:= 2Pi*Cos[pi/2*t]. Note the underscore after t in the lefthand side. Commented Sep 10, 2018 at 4:31

The major difference between = and := is that the first one evaluates its right-hand side while := doesn't. All weird behavior can be explained by this. We start with your initial example

a[t_] := -Pi Sin[Pi/2*t]


Even if you gave t a value before, this definition will work because the right part is not evaluated. Let's say you defined t=1 and you don't use := then the following would happen

t = 1;
aWrong[t_] = -Pi Sin[Pi/2*t];
?? aWrong


This is a useless function because the right side was evaluated using the global value for t. This is the reason why in most cases, you want to use := for functions. However, there are situations when you need to evaluate the right side even for a function.

Here is what doesn't work

vWrong[t_] := Integrate[a[t], t];
?? vWrong


Now, imagine what happens if you call vWrong[3]. The problem is that every instance of t will be replaced with 3 and you end up with

So what you really want is to solve the integral for an unknown t first and then use this inside your function definition. Several ways are possible but none of them are particularly beginner-friendly. Remember that we gave t a global value of 1, so we need to prevent that this is used in the integration.

Here is one way that blocks t so that it has no value, calculates the integral and then injects the solution into the function definition with :=.

Block[{t},
(v[t_] := #) &[Integrate[a[t], t]]
]


Of course, you can do the same thing using = because it will evaluate the right side anyway. You just have to be aware that in the evaluation, global variables like our t=1 are used. Therefore, we wrap this code in Block too

Block[{t},
v2[t_] = Integrate[a[t], t]
]


You can define s[t] in a similar way, but maybe this all is not necessary if you just want to work with the expressions and you don't need function definitions.

This here works too, is much more beginner-friendly and usually used

ClearAll[t];
at = -Pi Sin[Pi/2*t];
vt = Integrate[at, t]


I hope that helps in understanding the situation. The main thing you need to be aware of is when you need to evaluate expressions.

Edit

When you say, I need to be aware of when to evaluate an expression, is there a list of scenarios when I should and shouldn't evaluate an expression?

There are too many different situations to give a list. However, the general rule is to use := for functions. One of the exceptions is the problem you had. Here it helps if you ask yourself the question

Is there something on the right side of my definition that needs to be (can be) calculated upfront?

One famous example that broke the necks of many many users is the following. Assume you have a function that calculates the area of an expression up to a certain value tend:

func[tend_] := Integrate[-Pi Sin[Pi/2*$t], {$t, 0, tend}]


With your newly acquired knowledge, you know that the Integrate will not be evaluated during the definition, but each time you call func. This is disastrous when you try to plot it because func is called so many times

Plot[func[tend], {tend, 1, 10}]; // AbsoluteTiming
(* {6.35437, Null} *)


However, in this case, we can precalculate the integral even for an unknown tend. So when we use (note the =)

func2[tend_] = Integrate[-Pi Sin[Pi/2*$t], {$t, 0, tend}]


the integral is solved and calling func2 is extremely fast

Plot[func2[tend], {tend, 1, 10}]; // AbsoluteTiming
(* {0.034309, Null} *)


There are far too many people who waited hours for their plots to finished because they did not realize they can pre-calculate some things.

My final tip is, just try to be aware of these things and if in doubt, check your definitions with ?? and think about what gets evaluated.

• thank you for your detailed explanation. When you say, i need to be aware of when to evaluate an expression, is there a list of scenarios when I should and shouldn't evaluate an expression? or does it vary from expression to expression. Commented Sep 10, 2018 at 12:42
• @Tuits92 I have tried to elaborate a bit in the end of my answer. Commented Sep 10, 2018 at 14:41