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

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

Another example:
a = 1;
Print[a]@1
a - 1

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

One thing that needs special attention is parenthesis.
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
:

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:

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
:
Currently I consider this as an exception.
Of course in this case breakpoint can't be set on (a + b)
:

2. Breakpoints can't be set on atom.
1
a[b];
2
The break point set on b
won't work

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

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:

With this watchpoint, the evaluation will:
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
If you have the "Break on Evaluation" checked, evaluation will break whenever f
is evaluated i.e. it'll even break at
f
If you have the "Break on use as Function", evaluation will break at positions like:
f[1] := 2
f[1]

f[1] = 2;
f[1]

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

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

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
Store a trivial pure function in $Post
:
$Post = #&;
Set watchpoint on $Post
and check the "Break on Evaluation":

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.