38
$\begingroup$

re: Version 9. I typically write concise code and make a real effort to refactor. As such debugging has tended to take care of itself.

Recently, I've needed to assemble applications of more complexity, in that it they have deeper hierarchies of functions, lots of them, and often from multiple packages. So I've started to want just a bit more debugging help.

I prefer as simple development environment as possible, so I'd like to focus on debugging with native functionality of Breakpoints, rather than debugging functions from third parties or Workbench.

I just need to see what goes on in the code.

While, several questions on the site explore strategies and tactics for debugging. I have not found a concise description of how to effectively use the Breakpoints debugging functionality accessible from the menu items:

Evaluation > Debugger Controls > Show Breakpoints Window

either on this site, on Wolfram's site, or in the Mathematica documentation.

Opening the Breakpoints debugging window doesn't tell one much.

enter image description here

One would expect a clear way to set up breaks and variables to watch, and a way to run code to the specified point. In particular can and how can one:

  • set a series of breakpoints both at a functional level and within a function and
  • step through processing, point to point?

Some examples or mini-overview?

Thx.

$\endgroup$
6
  • 14
    $\begingroup$ if anyone can figure how to use the above evaluation->debugger then they should get 10,000 voting points added. The above tool is the most convoluted software tool I have ever seen. I really have no idea why is it even there as it is impossible to figure out and use in any practical way. Matlab debugger is the best and easiest debugger I've seen so far. I am hoping Mathematica will one day have such an easy to use debugger integrated in it, but I am not holding my breath for that. $\endgroup$
    – Nasser
    Aug 24, 2013 at 21:15
  • $\begingroup$ @Nasser -- Comforting to know, I haven't gone completely daft. Thx. $\endgroup$
    – Jagra
    Aug 24, 2013 at 21:41
  • 2
    $\begingroup$ @Nasser if you highlight some part of the code (eg with ctrl-.), set a breakpoint, and evaluate the code, doesn't it then break there and display the state? $\endgroup$
    – acl
    Aug 24, 2013 at 22:25
  • 4
    $\begingroup$ I commiserate. For laughs there is this page extolling the power and glory of the debugger. $\endgroup$
    – m_goldberg
    Aug 25, 2013 at 23:14
  • 1
    $\begingroup$ You can fight it all you want (I surely did), but in the end Workbench is the best solution. I'm only sorry I didn't switch to WB sooner. $\endgroup$
    – Ajasja
    Nov 10, 2013 at 21:21

4 Answers 4

15
$\begingroup$

The debugger in Mathematica is, in fact, a bit hard to use. However, it is functional. To create a breakpoint, one must select the WHOLE command. Just double clicking on the command name will do. Then you press the "Break at Selection" button in the debugger control panel. I still have no clear understanding what is considered a whole command from the Mathematica point of view. If the breakpoint doesn't work, I'll select the expression around it and try to make that a breakpoint.

In the example attached, selecting the "Print[...]" statement worked as a breakpoint, while selection only a "ToString[...]" command didn't stop the execution.

Mathematica Debugger

$\endgroup$
1
  • $\begingroup$ Which version were you using? With v9.0.1, win10 64bit, I can't reproduce the problem about ToString:i.stack.imgur.com/ZhqHN.png $\endgroup$
    – xzczd
    Jun 27, 2016 at 10:01
28
$\begingroup$

I believe I've figured out the correct way to use breakpoints :D

The Chinese edition of this answer can be found here.

In short, Breakpoints can only be set on a non-atomic incomplete expression, Watchpoints can only be set on Symbol.

…OK, maybe a bit too concise, let me elaborate a little.

1. Breakpoints must be set on an incomplete expression

a = 1;
Print[a]
a - 1

The break point set on Print[a] won't work

enter image description here

because Print[a] is already a piece of complete code, while Breakpoints can only be set on code piece that is inside a expression. Once Print[a] becomes a part of bigger code, no matter it's a head or an argument, the breakpoint will work. For example

a = 1;
1[Print[a]]
a - 1

enter image description here

Another example:

a = 1;
Print[a]@1
a - 1

enter image description here

A ; after Print[a] is also OK, don't forget ; is also a function:

a = 1;
Print[a];
a - 1

enter image description here

One thing that needs special attention is parenthesis.

  1. If the expression is an argument or a head, and it's wrapped by a pair of parentheses, for example

    f[(a + b)]
    
    (a + b)[f]
    

    then the breakpoint can't be set on a + b: enter image description here enter image description here

    I think this can be explained as: the debugger considers the code inside parentheses as a complete expression.

    In these cases, breakpoints must be set together with the parentheses: enter image description here enter image description here

  2. However, if the expression is already a complete expression, and it's wrapped by a pair of parentheses, for example

    (a + b)
    

    then the breakpoint can be set on a + b: enter image description here Currently I consider this as an exception.

    Of course in this case breakpoint can't be set on (a + b): enter image description here

2. Breakpoints can't be set on atom.

1
a[b];
2

The break point set on b won't work

enter image description here

because b is an atom:

AtomQ@b
(* True *) 

Notice that even if a non-atomic expression is stored in b, the breakpoint still won't work

b = c + d
a[b];
2

enter image description here

because this doesn't change the truth that b is an atom:

AtomQ@Unevaluated@b
(* True *)

3. Watchpoints is for breaking at Symbol

Now that we know Breakpoints can't be set on atom, is there any way to break at atom? The answer is yes, at least for atoms with head Symbol. We just need to set Watchpoints.

The Watchpoints panel can be found at the bottom of Breakpoints(Local) window. We just need to type in the interested Symbol and press Enter:

enter image description here

With this watchpoint, the evaluation will:

  1. If you have the "Break on Assignment" checked, evaluation will break at position like

    f = 1
    

    Notice SetDelayed seems not to be considered as assignment by the debugger i.e. the evaluation won't break at

    f := 1
    
  2. If you have the "Break on Evaluation" checked, evaluation will break whenever f is evaluated i.e. it'll even break at

    f
    
  3. If you have the "Break on use as Function", evaluation will break at positions like:

    f[1] := 2
    f[1]
    

    enter image description here

    f[1] = 2;
    f[1]
    

    enter image description here

    f[x_] = Sin[x];
    f[2]
    

    enter image description here

    f[x_] := Sin[x]
    f[2]
    

    enter image description here

Notice all the built-in functions and symbols are also atoms with Head Symbol:

Head/@{Print, E}
(* {Symbol, Symbol} *)

so Watchpoints can be set on them. An interesting example is, by setting watchpoint on $Post, you can execute code line by line. You just need to

  1. Store a trivial pure function in $Post:

    $Post = #&;
    
  2. Set watchpoint on $Post and check the "Break on Evaluation": enter image description here

  3. As shown above, the evaluation now breaks line by line. To run the next line, just press the "Continue" button on the "(Local)" panel.

4. Watchpoints is only for breaking at Symbol

Not to mention those non-automatic expressions like 1 + 1, f[a], etc., atoms whose Head aren't Symbol, for example "a", 1, 1.2, can not be set as Watchpoints, either.


All the examples above are tested under v9.0.1, win10 64bit. So far no counter-example for the aformentioned rule is found, at least in my limited test.

$\endgroup$
21
$\begingroup$

There is a fundamental problem with breakpoints and Mathematica: Mathematica code is not typically attached to a source code file. It simply exists in-memory as a set of transformation rules on expressions. These transformation rules can be created (among other ways) by:

  • Loading a package file. In this case they correspond to the source code in the file.

  • Evaluating an input cell. In this case they still correspond to the code in the cell. But cells are too easy to change ... what if the cell gets modified (as it often does) or it gets deleted?

  • Completely programmatically. There is no corresponding source code (i.e. text) at all.

Most other languages have a workflow where we (1) write the code in a file (2) run the code. A Mathematica workflow is typically much more interactive: we write code in input cells, evaluate it, modify the input, re-evaluate, etc.

Breakpoints only work well if there is a stable source file, which does not get modified often. Breakpoints are set within the source (text) of the program. They are often tied to line numbers (another thing that's not very useful with Mathematica code).

My suggestion is: Do not use traditional breakpoints!

There will always be problems with traditional breakpoints because they are just not a good fit for Mathematica as a programming language, and and even worse fit for the typical Mathematica workflow.

What I do instead is that I insert explicit an Assert[False] into the code at the point where I want to allow a break. Then I turn on "Break at Asserts". This behaves like a breakpoint, but since it is tied to the abstract expressions that make up a Mathematica program, not to the textual source code. Thus it is much more reliable, and eliminates most of the frustrating problems with the debugger.

While I don't use the debugger often, I do keep using it, and I do find that it helps pinpoint problems. I always use this method to break at the point of my choice.

$\endgroup$
7
$\begingroup$

I never managed to use the built-in debugger. However if you are willing to use another IDE, the Wolfram Workbench 2.0 is a Mathematica IDE based on eclipse. It provides great debugging capabilities: step by step execution, breakpoints, variable watch, Mathematica front-end integration...

$\endgroup$
2
  • 4
    $\begingroup$ Workbench is much, much easier to debug with - but will not work with 10. $\endgroup$ Apr 7, 2015 at 20:17
  • $\begingroup$ Workbench 3 now works also for the latest versions as well. And it's free. $\endgroup$
    – faysou
    Dec 26, 2016 at 14:44

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.