554
$\begingroup$

As you may already know, Mathematica is a wonderful piece of software.
However, it has a few characteristics that tend to confuse new (and sometimes not-so-new) users. That can be clearly seen from the the fact that the same questions keep being posted at this site over and over again.

Please help me to identify and explain those pitfalls, so that fewer new users make the mistake of walking into these unexpected traps.

Suggestions for posting answers:

  • One topic per answer
  • Focus on non-advanced uses (it's intended to be useful for beginners/newbies/novices and as a question closing reference)
  • Include a self explanatory title in h2 style
  • Explain the symptoms of problems, the mechanism behind the scenes and all possible causes and solutions you can think of. Be sure to include a beginner's level explanation (and a more advanced one too, if you're in the mood)
  • Include a link to your answer by editing the Index below (for quick reference)

Stability and usability

Syntax and semantics

Assignment and definition

General guidelines

Graphics and images

Tricky functions

$\endgroup$
16
  • 7
    $\begingroup$ Few suggestions: 1. old definitions in memory and "overloaded" functions like f[x_]:=a; f[x_Integer]=b; 2. Forgotten underscore in patterns f[x]=a 3. Set vs SetDelayed; 4. m = {{1, 2}, {3, 4}} // MatrixForm and then Eigenvalues[q]; 5. Plotting complex function produces empty plot without any warnings. $\endgroup$ Commented Jan 24, 2013 at 22:23
  • 3
    $\begingroup$ I want to throw $HistoryLength in there, a memory management in general category including MaxMemoryUsed and MemoryConstrained etc $\endgroup$
    – ssch
    Commented Jan 25, 2013 at 0:03
  • 5
    $\begingroup$ Suggestion: If appropriate to the problem, force Mathematica to use approximate numerical algorithms to avoid the computational overhead of their symbolic counterparts. There are several ways to do this (e.g., NIntegrate vs. Integrate, using real approximate numbers instead of integers in equations, etc). $\endgroup$
    – Cassini
    Commented Jan 25, 2013 at 3:51
  • 4
    $\begingroup$ Suggestion: mathematica.stackexchange.com/q/18483/193 (Using the result of functions that return replacement rules) $\endgroup$ Commented Jan 26, 2013 at 7:46
  • 7
    $\begingroup$ Maybe there should be a (short) answer about security. Most people don't realize mathematica has a large set of functions that are capable of taking over your computer entirely, or as a more specific example, activating your webcam (CurrentImage). $\endgroup$ Commented Aug 8, 2013 at 11:19

37 Answers 37

1
2
12
$\begingroup$

Omitting ; can cause unexpected results in functions

A missing ; somewhere inside a function is my number one reason for time-consuming debugging because there are no error messages indicating that something is wrong and where the error is. Here a simple example:

Assume you write a function that performs some iterative calculation in a While loop and once some condition is fulfilled it returns the result (in the example just the input variable). To see the progress of your function you print the iteration counter at every iteration, but forget to put a semicolon at the end of the print command.

f1[x_] := 
  Block[{counter},
    counter = 0;
    While[counter < 5,
      counter += 1;
      Print[counter]
      (* Note the missing ; after the Print[] command. 
         This will not throw an error. *)
      If[counter > 2, Return[x]];];];

Now you execute f1[20]. It prints

f1[20]

1

2

3

4

5

and generates no output. It seems that the Return[x] part of the code did not work. However, the If experesion works just fine, as can be seen when putting some debug print message just there:

f2[x_] := 
  Block[{counter},
    counter = 0;
    While[counter < 5,
      counter += 1;
      Print[counter]
      (* Note the missing ; after the Print[] command. 
         This will not throw an error. *)
      If[counter > 2, Print["if has been successfully evaluated"]; 
      Return[x]];];];

With the result

f2[20]

1

2

3

if has been successfully evaluated

4

if has been successfully evaluated

5

if has been successfully evaluated

The problem is that Return behaves differently if there is no ; after the Print command somewhere up in the chain. In fact, due to the missing ; the Return only returns from the not properly bundled statement Print[counter]If[...] (remember that newlines are just decorations) and not from the actual function. Fixing the issue solves the problem:

f3[x_] := 
  Block[{counter},
    counter = 0;
    While[counter < 5,
      counter += 1;
      Print[counter];
      If[counter > 2, Print["if has been successfull evaluated"]; 
      Return[x]];];];

f3[20]

1

2

3

if has been successfully evaluated

20

It is possible to see the change by the different indent of what comes after the Print.

Note: this answer was written by Felix (user:38410) as an update to another answer, but I have made it a stand-alone answer because it really deals with a different pitfall than the other answer. [m_goldberg]

$\endgroup$
2
10
$\begingroup$

In symbolic algebra, x[1] is quite different from x1. This one-liner avoids problems and gets nice subscript formatting.

x[i_Integer] := x[i] = 
   With[
     {u = Unique[x]}, 
     Format[u] = Subscript[x,i];
     u
   ]

There are many advantages to using x[1], x[2], ... as symbolic variables, such as creating a list of them with Array[x, 5] to pass into Solve[], or creating a list of expressions with Table[x[i] + x[i + 1], {i, 5}].

There are also some good reasons to avoid this practice. Some operations choke on them. Writing x[1] sometimes declares that x is a function of one variable only and x[1] may be assumed constant.

They also are not formatted as subscripts. Using Subscript[x,1] as a variable also invites trouble. The above one-liner solves both problems.

Array[x, 4] then displays as $\left\{\text{x}_1,\text{x}_2,\text{x}_3,\text{x}_4\right\}$, actually (say) {x$2136, x$2152, x$2163, x$2164}.

Table[x[i] + x[i + 1], {i, 3}] returns $\{\text{x}_1 + \text{x}_2, \text{x}_2 + \text{x}_3, \text{x}_3 + \text{x}_4\}$.

Further reading:

$\endgroup$
6
  • $\begingroup$ ??x does not show the internal form. DownValues[x]//InputForm does, but does not list the Format definitions. How can I make Information["x"] print the internal values? How can I discover what Format definitions exist? $\endgroup$ Commented Feb 7, 2017 at 19:36
  • $\begingroup$ I made a new answer because this one is very different from what 3 people downvoted. I hope it will be judged on its merits. $\endgroup$ Commented Feb 7, 2017 at 19:38
  • $\begingroup$ FullDefinition[x] should show what you want. $\endgroup$
    – Mr.Wizard
    Commented Feb 8, 2017 at 3:13
  • $\begingroup$ It seems FormatValues[] contains the definitions. It's hard to print it, though, because the Format gets applied even to things inside HoldComplete[]. FormatType inside the MakeBoxes rule triggers an error message. With[{XX=x[100]}, With[{fvxx=FormatValues[XX]}, FormatValues[XX]={}; Print[fvxx/.{Format->"Format",Subscript->"Subscript"}];FormatValues[XX]=fvxx ]]; prints {HoldPattern[Format[x$145]] :> Subscript[x, 100], HoldPattern[MakeBoxes[x$145, FormatType_]] :> Format[Subscript[x, 100], FormatType]} $\endgroup$ Commented Feb 8, 2017 at 6:54
  • 1
    $\begingroup$ Oh, sorry, I finally understand what you're talking about. Consider FullDefinition[x] // InputForm $\endgroup$
    – Mr.Wizard
    Commented Feb 8, 2017 at 7:45
7
$\begingroup$

Plot functions do not print output (Where are my plots?)

Quite often new users write something like this and are surprised that no plots are produced:

For[
  n = 1,
  n <= 3,
  n++,
  Plot[Sin[x*n], {x, 0, 2 Pi}]
]

Since version 6 of Mathematica the plot functions (Plot, Plot3D, ListPlot, ContourPlot, ParametricPlot, etc.) do not print their output but instead evaluate to a Graphics or Graphics3D expression, just as 2 + 2 evaluates to 4.

To see the output of Plot in this loop one needs to write it to the Notebook as a side-effect which is exactly what Print does. This can be done explicitly (Print[ Plot[. . .] ]) or by setting $DisplayFunction to something with a side-effect as it was in versions 5.2 and earlier.

A better approach is to collect and display the direct output of Plot as it may be manipulated like any other expression. The most direct substitute for the For loop is Table:

Table[
  Plot[Sin[x*n], {x, 0, 2 Pi}],
  {n, 1, 3}
]

enter image description here

This returns (evaluates to) a List containing three Graphics expressions. These expressions are displayed by the Front End as graphical objects that may be interactively manipulated. This output may be assigned to a Symbol or Indexed Object. It may be displayed in particular arrangements using e.g. Row, Column, Multicolumn, GraphicsRow, etc., or animated with ListAnimate

The Graphics expressions may be modified with the full range of expression manipulation tools, sometimes referred to as post-processing as one starts with the existing plot output.

$\endgroup$
7
$\begingroup$

PerformanceGoal -> "Speed" can yield irreproducible results.

For example, the procedure doPlot below

  1. computes a SmoothKernelDistribution on a fixed data vector (DATA);
  2. defines a pdf function based on this distribution;
  3. plots the pdf function.
doPlot[] := Module[{
    pdf,
    distribution = SmoothKernelDistribution[DATA,
                                            "StandardGaussian", "Biweight", 
                                            PerformanceGoal -> "Speed"]
   },
   pdf = Function[x, PDF[distribution, x]];
   Plot[pdf[x], {x, 0, 180000}, PlotRange -> {All, {0, 0.00004}},
        Axes -> False, Frame -> True, FrameTicks -> None,
        ImageSize -> 50, AspectRatio -> 1, ImagePadding -> {{0, 1}, {1, 0}}]
]

Since doPlot takes no arguments, one could hope that it would produce the same results every time, but this is not the case. The figure below shows the result of 100 runs of doPlot.

Mathematica graphics

It appears that "reproducibility" is one of the ingredients of "Quality" that one forfeits when one specifies PerformanceGoal -> "Speed". This is not outlandish, of course, but it is not self-evident either.

$\endgroup$
6
$\begingroup$

Assocation component access [] vs [[]]

With MMA we spend a lot of time manipulating lists where access to components is done by [[index]], this can make us forget that when using Association keys, the syntax is [key].

If keys are integers this can be a source a bug:

a = <|0 -> "A", 1 -> "B", 2 -> "C", 3 -> "D"|>

a[[2]]

Out: = "B"

a[2]

Out: "C"

If you want to use Part to access associations with arbitrary keys, you need the wrapper Key:

a[[Key[2]]]

Out[]= "C"

This can be used to access multiple keys as well:

a[[{Key[2], Key[3]}]]    

Out[]= <|2 -> "C", 3 -> "D"|>
$\endgroup$
4
$\begingroup$

Understanding $Context, $ContextPath the parsing stage and runtime scoping constructs

A symbol in Mathematica can never be without a context. We can assume that the internal representation of any symbol stores a string of the form "context`symbol".

But for you as a programmer, there are ways to enter a symbol without stating it's full context: x, Sin, `x are all valid inputs.

The values of $Context and $ContextPath at the parsing stage determine which symbol is actually meant by the above inputs.

This settles which symbols are initially used in the expression put together that will be submitted to the evaluator. You can display the actual name of symbols in a snippet of code by printing the "FullForm" of an expression with context as follows:

Hold[

(*your code here*)
x

] /. x_Symbol :> Context@x <> SymbolName@Unevaluated@x
(*=>*)
"System`Hold"["Global`x"]

(see here for more ways of doing this). Note that Mathematica strips the context whenever possible, even in FullForm, to present to you more or less what you (supposedly) entered: Global`y is displayed as just y.

However, at runtime, an x that is parsed as Global`x might well become something else still. Let's try the following:

Hold[
  
  Module[{x}, x]
  
  ] /. x_Symbol :> Context@x <> SymbolName@Unevaluated@x

gives

"System`Hold"["System`Module"["System`List"["Global`x"], "Global`x"]]

So the variable is parsed as Global`x. But evaluating Module[{x}, x] we get something like x$11686. Module changed every literal occurrence of Global`x to a variable created probably via Unique@Unevaluated@x before executing the code.

However, this replacement is aware of some scoping constructs of the language which it will not enter. Rule is one of them:

Module[{x}, {x, x_ -> x}]

gives

{x$12264, x_ -> x}

And not say {x$12264, x$12264_ -> x$12264}.

With and Function are also scoping constructs which interact. Here for example, every x is parsed as Global`x:

Hold[
  
  With[{y = x}, Function[{x}, x + y]]
  
  ] /. x_Symbol :> Context@x <> SymbolName@Unevaluated@x
(*=>*)
System`Hold[System`With[System`List[System`Set[Global`y,Global`x]],System`Function[System`List[Global`x],System`Plus[Global`x,Global`y]]]]

But in the result of evaluation a new symbol x$ will have been created to resolve a (potential) name clash:

Function[{x$}, x$ + x]

BeginPackage, Begin and messages like

*::shdw: Symbol * appears in multiple contexts {*}; definitions in context * may shadow or be shadowed by other definitions. >>

also fall into this complex of considerations.

Related questions and "articles"

Many questions tagged with variable-definitions scoping and contexts deal with this topic. Here's a selection:

Context of localised (dynamic) symbols

DynamicModule Initialization is not executing when expected?

How to scope `Pattern` labels in rules/set?

How to make a function like Set, but with a Block construct for the pattern names

tutorial/VariablesInPureFunctionsAndRules

package import problem in mathematica (Stackoverflow)

$\endgroup$
5
  • 4
    $\begingroup$ Is this really a "common pitfall awaiting new users?" It's tricky admittedly, but hardly a pitfall until you start writing packages, imo. $\endgroup$
    – Michael E2
    Commented Jul 3, 2016 at 18:37
  • $\begingroup$ Even when you want to use packages (which is basic/should be encouraged) you need to know that you cannot put (Needs["Apackage`"]; PackageFunction[...];) into one expression (or one line in the frontend!): You need to have one roundtrip to the kernel to have Needs update the $ContextPath, c.f. e.g. stackoverflow.com/questions/4664091/… . And I think knowing what exactly an identifier denotes is crucial in any programming language. $\endgroup$
    – masterxilo
    Commented Jul 3, 2016 at 23:30
  • 2
    $\begingroup$ @MichaelE2 I think you both are right but due to the lack of a proper place it is good to have it here. Maybe we could think about another guidelike topic: "Fundamentals that are spread too thinly across documentation", it would fit there best, don't you think? $\endgroup$
    – Kuba
    Commented Jul 4, 2016 at 5:52
  • 2
    $\begingroup$ I agree with @Michael and @Kuba: currently this post is intended for experienced users who wish to write a package. The (Needs["Apackage`"]; PackageFunction[...];) case should be included as a point into one of the multi-point answers here (I think this answer perfectly fits). Probably we should move this answer to a new thread and include in the OP here a link to that thread with wordings like "This thread is intended primarily to those who learn the basics of the WL. For discussion on subtle/professional topics see that thread". $\endgroup$ Commented Jul 4, 2016 at 9:19
  • $\begingroup$ @MichaelE2 and mastexilo, I tied to polish this topic to make it a generic one about parsing, suggestions appreciated. 119187 $\endgroup$
    – Kuba
    Commented Jul 15, 2016 at 7:15
3
$\begingroup$

Association has HoldAllComplete attribute

Association is not just another head denoting a special kind of list of rules or a certain kind of object. It has some properties that make querying it more efficient, but also cause it to behave differently from a List. You should be aware of this if you intend to use Associations as a data structure for object oriented programming.

Let me illustrate. Say we want to have a single expression representing a person with the attribute age. We might use a custom head, list or association to store a rule assigning "age" to something. A list and custom head person will support template objects which have some parameters undefined at the time of their definition. But a head with HoldAll such as hperson and Association will not fill in the blanks once you define them.

ClearAll[p1, p2, p3, x, getAgeSquared, hperson];

(*make hperson behave more like Assocation*)
SetAttributes[hperson, HoldAll];

p1 = person["age" -> x]
p2 = List["age" -> x]
p3 = Association["age" -> x]
p4 = hperson["age" -> x]

getAgeSquared@_["age" -> x_Real] := x^2;
(*these stay unevaluated*)
getAgeSquared@p1
getAgeSquared@p2
getAgeSquared@p3
getAgeSquared@p4

x = 3.;

(*note that x is not inserted into structures with HoldAll*)
p1
p2
p3
p4

(*consequently, you cannot do the following successfully with \
Assocation and hperson*)
getAgeSquared@p1
getAgeSquared@p2
getAgeSquared@p3
getAgeSquared@p4

The output is

person[age->x]
{age->x}
<|age->x|>
hperson[age->x]

getAgeSquared[person[age->x]]
getAgeSquared[{age->x}]
getAgeSquared[<|age->x|>]
getAgeSquared[hperson[age->x]]

person[age->3.]
{age->3.}
<|age->x|>
hperson[age->x]

9.
9.
getAgeSquared[<|age->x|>]
getAgeSquared[hperson[age->x]]

Example confusion

Using Associations and Pattern matching in numerical functions possibly broken

$\endgroup$
1
  • 4
    $\begingroup$ I must note that this answer is written in a clumsy way and even to me it is almost impossible to follow your thought (despite the fact that I know in principle what you want to say). I would recommend to rewrite it from the scratch or delete. $\endgroup$ Commented Jul 4, 2016 at 1:47
1
2

Your Answer

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

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