Vocabulary/Debug
Debugging
Debugging is isolating problems in a program. This requires a clear idea of what the code is meant to accomplish and a willingness to invest the time to locate points of failure. Here, it's best to focus on the first point of failure.
If you are not familiar with how the code functions, it's best to have some small relevant working examples to compare against. You need to be able to see the data you are working with.
How to debug an explicit definition
A typical debugger for a modern programming language lets you set one or more stops in the code you are maintaining. Then when you run the code, execution will halt at your first stop.
You then have access to the collection of features the language vendor sees fit to offer. With J these features include:
- viewing the line of code at which the stop was set
- viewing the state of the function stack
- examining the values of given variables
- single-step execution over successive lines of code
- resuming execution (maybe to halt at the next stop, or at the error in question).
If you use APL, you'll know the debugger is always enabled. Whenever an APL function suspends (e.g. halts with an error) all the debugging features of APL are instantly available, and the state of the session (values of local variables, etc.) is preserved for you to investigate.
This is not so in J. Having the debug features always available was considered unacceptably inefficient in normal use. This means that when J encounters an error during execution, and displays the appropriate error message, J returns to immediate mode, clearing down the function stack and thus discarding the evidence for why the error occurred.
The J debugging features are collectively known as debug.
To debug J code after encountering an error, you first need to activate debug, then run the code again to replicate the error.
Once you've activated debug then, when an error occurs, instead of clearing down the stack and losing the evidence, J enters debug mode (shown by a prompt of 6 spaces instead of the usual 3) and waits for you to tell it what to show you.
NOTE: Only explicit definitions can be investigated using debug. But these can be either verbs or modifiers.
With tacit definitions there are no "local variables", so when an error is triggered there is little to work with beyond the error message itself.
Working with the J debugging features
When the debugger is active, JE adds diagnostic information at run time to allow full examination of the system at a point of failure or a breakpoint. When you are developing code that you expect to have to debug, you should engage the debugger first thing.
Live debugging
The J debugging features, collectively known as debug, are detailed here.
Debug is built around the Foreign: (13!:*). You can call the (13!:*) verbs directly (not an easy task for a beginner), or use whatever task support for debug is available in your J IDE.
- If you are using JQt,enter debug using ctrl+k and use the window that comes up.
- If you are using JConsole, the standard library (stdlib) defines in the _z_ locale a set of mnemonic cover verbs for the 13!:* verbs. Their names all begin db* and are shown in the "Name" column of the table for the Foreign: (13!:).
Thus, to enable debug in JConsole, enter the following:
dbr 1
and to disable it again after you've finished debugging:
dbr 0
NOTE: Setting dbr 1 does not straightaway enter debug mode. That doesn't happen until the next time an error is encountered, or execution reaches a stop you have set inside some explicit definition.
Until that happens, you won't see anything different from normal J behavior.
So don't go thinking dbr 1 hasn't worked. It's waiting there silently like a landmine, ready to go bang under the error in question.
Postmortem Debugging
If you didn't turn on debugging before your error, you will be prompted to turn it on after you hit an error. This is postmortem debugging. Postmortem debugging is exactly like live debugging except that the program cannot be restarted. You are free to look through the stack frames to see what went wrong.
Typical debug workflow in JConsole
If you hit an error in the body of an explicit definition, and want to fix it, then these are the simpler steps you'd typically take:
- Enable debug with: dbr 1
- Reproduce the error (J goes into debug suspension – 6-space prompt)
- Inspect the pronoun(s) being worked on by the offending J sentence, especially local pronouns, y and maybe x
- Inspect the whole body of the suspended verb definition
- If execution went too far, set a stop on the offending line of code, for a future re-run.
- At any stage, quit debug with: dbr 0
The things you can do in debug mode are rich and interesting. You can even fix code during the debug session. But until you get a deep feel for debug, you'll soon get into trouble and become seriously confused.
RECOMMENDED: As soon as you've spotted what the problem is, quit debug with: dbr 0
Forgetting to do this is a common source of distress and confusion, as the J function stack fills with garbage and ties itself in knots.
Now back up the code you propose to fix, then go ahead and fix it.
>>> UNFINISHED STUB <<<