I am studying the question [What are the most common pitfalls awaiting new users?](https://mathematica.stackexchange.com/questions/18393/what-are-the-most-common-pitfalls-awaiting-new-users/25616#25616)  

Up to now, I have fulfilled some of the parts but yet don't understand which this problem is related to?  

Consider the following code: 

In my notebook, which is a test notebook to try out the codes in the above question, I have defined function **f** in 3 different places with the following sequence: 

```
f[x_] := Expand[x^2](*SetDelayed*)
f[a + b]        
(* a^2 + 2 a b + b^2 *)

f[x_] := Sqrt[x] /; x > 0(*Condition[patt,test]*)
f[2]        
(* Sqrt[2] *)

f[-2]        
(* f[-2] *)

f[x_?NumericQ] := NIntegrate[Sin[t^3], {t, 0, x}]  
f[2]        
(* Sqrt[2] *)

```

Getting the answer $\sqrt{2}$ for $f[2]$ clued that there exists a problem and function $f$ is not updated by its new definition. So I wrote this code: 

```
?f  

Global`f
f[x_]:=Sqrt[x]/;x>0

f[x_?NumericQ]:=NIntegrate[Sin[t^3],{t,0,x}]

f[x_]:=Expand[x^2]

```

And to see which of these definitions will be used each time the function $f$ is evoked, I wrote: 

```
f[2]        
(* Sqrt[2] *)

f[a + b]  

(* a^2 + 2 a b + b^2 *)

f[6]        
(* Sqrt[6] *)

f[-2]        
(* 0.451948 *)

```

Now a few questions rise up: 

1. which characteristic of the Wolfram language causes this (commands
not having side effects, precedence of operators, .....,any thing
else)?
2. What is the application of that characteristic in math that
convinced the wolfram language developers to design the language
this way?
3. Do we have to `clear` , `Unset` or `UnsetDelay` variables and functions each
time we finish our work with them?
4. Is there a way to tell wolfram language explicitly which definition
of $f$ should be used?
5. Is their something like `local variable`, `private function` in
Wolfram language that enables us define variables just when we want
to use them and better manage the memory (just like C++)?