10
$\begingroup$

Forgive me if this question is very basic; I've learned Mathematica mostly by example.

In most programming languages, there is a clear distinction between variables and functions: variables hold values, and functions take some values and return some others. But in Mathematica this becomes fuzzy. For example, I could this:

f = x^2
f /. x->2
Plot[f, {x,1,2}]

or this:

f[x_] := x^2
f[2]
Plot[f[x], {x,1,2}]

and in both cases I get the same result, namely 4 and a plot. I understand the difference between = and := as having to do with delayed vs. immediate evaluation, but the overall difference between the two ways of defining "functions" is not so clear. Where would these produce different results? Why would you choose one over the other?

$\endgroup$
5
  • $\begingroup$ This feels like a really big question. The reason there's not quite a clear distinction between these two is that everything in Mathematica 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... $\endgroup$
    – march
    Sep 27, 2016 at 16:16
  • 3
    $\begingroup$ A big question, but for everyday life, not a big problem : try not to use the first block of code, because if you do x=1 before your code, it doesn't work anymore. $\endgroup$
    – andre314
    Sep 27, 2016 at 16:33
  • 3
    $\begingroup$ If you're looking for a deeper understanding, Leonid's book/tutorial is a great place to start. $\endgroup$
    – N.J.Evans
    Sep 27, 2016 at 16:47
  • 3
    $\begingroup$ It is somewhat a terminology issue, but very roughly, I would call a function any construct that has a clear and explicit way to pass its arguments into its body, while a variable is simply a reference to an expression it stores. $\endgroup$ Sep 27, 2016 at 17:02
  • 4
    $\begingroup$ Your feeling is anticipated in the docs: Everything Is an Expression. The distinction between "variable" and "functions" begins with understanding the different kinds of values symbols can have and how they are applied in the evaluation sequence. $\endgroup$
    – Michael E2
    Sep 27, 2016 at 17:12

1 Answer 1

9
$\begingroup$

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. InBlock, the symbols are interpreted as the same, sog` evaluates to 4.

For more information about scoping, see What are the use cases for different scoping constructs?

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.