Advice
The definition of what we think of as a "function", i.e.
f[x_] := x^2
is safer than
g = x^2
because in the first case, x
isn't a global variable but rather the name of a Pattern
to be matched, whereas in the second case, x
refers to some (possible undefined but maybe not!) global symbol, and so you can run into issues. For instance, you might have set x
to a number previously and forgotten about it, which then leads to problems in later code. Maybe 1% of the questions we get here arise from this very issue.
Disambiguation/Explanation
The reason there's not quite a clear distinction between these two is that in Mathematica, Everything is an Expression, and Mathematica applies replacement rules to the expressions; these rules are attached to the symbols, and depending on the pattern in the replacement rule, the replacement works in slightly different ways.
To illustrate with your examples:
Clear@g
g = x^2;
OwnValues@g
(* {HoldPattern[g] :> x^2} *)
Associated with g
is a replacement rule that replaces every instance of g
with the expression x^2
automatically.
Clear@f
f[x_] = x^2;
DownValues@f
(* {HoldPattern[f[x_]] :> x^2} *)
x_
is a Pattern
that matches any expression (it is a wild-card), and names the expression x
so that it can be used on the right-hand side of a rule. Associated with f
is a replacement rule that replaces every instance of f[x_]
---that is "f-of-something"--- with the expression x^2
automatically. Note that when this matches, the x
isn't the symbol x
but rather whatever was put in the x_
spot.
f[2]
(* 4 *)
f[a + Sin[b]]
(* (a + Sin[b])^2 *)
This becomes important when you have to worry about scoping. In your plot examples, both
Plot[g, {x, 1, 2}]
Plot[f[x], {x, 1, 2}]
work, but this because Plot
effectively uses the Block
scoping construct, which blocks off any definitions of the symbol x
but still uses that symbol. Another scoping construct is Module
, which actually creates a new symbol.
For instance, note the following behavior. Using again
Clear@f
f[x_] = x^2;
Then Block
does this:
Block[{x}, Print[x]; x = 2; Print[f[x]]]
(* x *)
(* 4 *)
Contrast this with Module
, which does this:
Module[{x}, Print[x]; x = 2; Print[f[x]]]
(* x$3780 *)
(* 4 *)
Within Module
, we declare x
as a variable local to the construct, but behind the scenes Mathematica re-names the variable. Block
doesn't do that. However, since we use f[x]
in Module
, x
in f[x]
is interpreted as the local x
, and so it evaluates to 4.
Now, for the other version:
Clear@g
g = x^2;
Then,
Block[{x}, Print[x]; x = 2; Print[g]]
(* x *)
(* 4 *)
and
Module[{x}, Print[x]; x = 2; Print[g]]
(* x$3776 *)
(* x^2 *)
Because g
is directly replaced with x^2
, rather than the Pattern
f[pat_]
getting replaced by pat^2
, Module
treats the two x
's as different objects, and so g
evaluates to x^2
in Module. In
Block, the symbols are interpreted as the same, so
g` evaluates to 4.
For more information about scoping, see What are the use cases for different scoping constructs?
x=1
before your code, it doesn't work anymore. $\endgroup$