48 | Debugging Your Code |
Even the most experienced programmers have to spend time debugging their code. It’s an inevitable part of programming. But in the Wolfram Language it’s particularly easy, especially if you follow a few principles.
The first and most important principle is to try out any piece of code you write. Because the Wolfram Language is interactive—and symbolic—you can always instantly do this. So even if you just make a tiny change, run your code again, and see if your test examples still work. If they don’t, fix the code before you go on.
The Wolfram Language can sometimes tell as soon as you type something in that it’s likely to be wrong—and then it’ll color it red.
A piece of code with various problems, indicated with red:
WordCloud[
Nest[Join[#, Length[] + Reverse[#, 1, 2]] &, {0}, m],
Spacings -> 0]
Once you run a piece of code, the Wolfram Language can also often tell if things have gone obviously wrong—in which case it’ll display a message. The code here ends up, for example, asking for the first element of a length-0 list.
First[Cases[{1, 2, 3, 4}, 777]]
Sometimes the Wolfram Language may not know what to do with something, but it may not be sure there’s a problem. In such cases, it’ll just leave the input unchanged and return it in a symbolic form that can later get a definite value.
Without values for a, b and c, the Wolfram Language just returns this unchanged:
Graph[{a, b, c}]
If you generate graphics with symbolic pieces that can’t be rendered, you’ll get a pink box:
Graphics[{Circle[{0, 0}], Disk[{a, b}]}]
As you build up functions, it’s quite common to have fragments of code that you want to test without finishing the function. You can do this by setting values of variables using With—which works like Module, except it doesn’t allow values to be reset.
With[{m = 4}, Nest[Join[#, Length[#] + Reverse[#]] &, {0}, m]]
When debugging takes a long time it’s usually because one’s made the wrong assumption about what one’s code is doing. And in my experience, the best way to overcome this is just to systematically analyze how the code behaves, making tables of results, generating visualizations, testing out assertions and so on.
Make plots to see what the code is doing:
ListLinePlot /@
Table[Nest[Join[#, Length[#] + Reverse[#]] &, {0}, m], {m, 6}]
Sort[With[{m = 4}, Nest[Join[#, Length[#] + Reverse[#]] &, {0}, m]]]
Systematically check this up to m=10:
Table[Sort[Nest[Join[#, Length[#] + Reverse[#]] &, {0}, m]] ==
Range[0, 2^m - 1], {m, 10}]
Sometimes it’s not sufficient just to see the final result of a piece of code; you need to see what’s going on inside as well. You can insert the function Echo anywhere to print intermediate results or values from your code.
Echo prints values, but does not interfere with the result:
Table[Echo[n]^2, {n, 3}]
1
2
3
If you’re running a long computation, you can monitor its progress using Monitor.
Continuously show (with a frame) the value of n reached so far:
Monitor[Table[PrimeQ[2^2^n + 1], {n, 15}], Framed[n]]
Echo and Monitor just display things. If you want to actually capture intermediate results, you can do it using Sow and Reap.
Reap[Total[Table[Sow[n], {n, 5}]]]
Last[Reap[Nest[Join[#, Sow[Length[#]] + Reverse[#]] &, {0}, 10]]]
With[{x=value},expr] | compute expr with x replaced by value | |
Echo[expr] | display and return the value of expr | |
Monitor[expr,obj] | continually display obj during a computation | |
Sow[expr] | sow the value of expr for subsequent reaping | |
Reap[expr] | collect values sowed while expr is being computed |
48.1Correct the program Counts[StringTake[#, 2]&/@WordList[]] for counting possible first two letters in words. »
48.3Use Sow and Reap to get a list of all cases where #/2 is used in Nest[If[EvenQ[#], #/2, 3#+1]&, 1000, 20]. »
Can I cause a problem by just trying to run a piece of code?
Not unless your code is for example set up to delete something. The Wolfram Language has protections against “obviously wrong” infinite loops and so on. If something is taking too long, you can always abort it. If you’re really concerned about resources, use TimeConstrained and MemoryConstrained.
Is there a most common type of bug in Wolfram Language code?
Not really. The design of the language makes all sorts of bugs that are common in other programming languages rare. For example, “off by one” errors are common in languages where you’re always explicitly manipulating loop variables, but are rare when you’re using Wolfram Language “whole-list” functions like Table.
If I can’t figure out what’s going on, is it worth just trying random things?
If you think you’re close, it’s often not crazy to try making small random changes to code to see what happens. Since in the Wolfram Language simpler code is usually more likely to be correct, it’s not uncommon to hit the code you want by a small amount of random searching.
Is there a way to do interactive step-by-step debugging in the Wolfram Language?
Yes (at least with a native desktop interface)—though it’s rarely used. Given the structure of the Wolfram Language, systematically capturing and analyzing intermediate results is almost always a better approach.
When there’s a message, how can I tell where it was generated?
Click the
next to the message, then press Show Stack Trace. This will show you the stack of functions in which the message was generated.
\!\(\*
GraphicsBox[
TagBox[RasterBox[CompressedData["
1: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
Qd72aKKM3iv+k/H/DybC7Q4=
"], {{0., 86.94737205227011}, {110., 9.947372052270111}}, {0, 255},
ColorFunction->RGBColor,
ImageResolution->{72., 72.},
SmoothingQuality->"High"],
BoxForm`ImageTag["Byte", ColorSpace -> "RGB", Interleaving -> True],
Selectable->False],
DefaultBaseStyle->"ImageGraphics",
ImageSize->{22.116394042968622`, Automatic},
ImageSizeRaw->{110., 77.},
PlotRange->{{0, 110.}, {0, 77.}}]\)
How can I tell what’s wrong when a piece of graphics is “pinked”?
Hover over it and you’ll see the underlying symbolic expression. Or press the + to print messages.
What is the code that makes the fractal-like graphics doing?
It’s making a Gray code—an ordering of integers so that only one binary digit changes at each step.
- If Dynamic[x] appears in a notebook, it’ll display as the dynamically updated current value of x, giving you a way to produce a real-time display of what’s going on inside a program.
- EchoFunction, EchoTiming and EchoEvaluation are useful variants of Echo.
- The Wolfram Language has various mechanisms for bulletproofing code. An example is Enclose and Confirm, which allows you to confirm that your program didn’t fail, and if it did, fall through to the enclosing Enclose.
- For large-scale software development, the Wolfram Language has a built-in framework for creating and running systematic tests, with functions like VerificationTest and TestReport.
- A major goal of good language design is to encourage people to write correct code.