Advice for Debugging

morals

Finding your bug is a process of confirming the many things that you believe are true — until you find one which is not true.
—Norm Matloff

“Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it.”
—Brian W. Kernighan

the general outline

  1. Google the error
  2. Make your error repeatable
  3. Figure out where the error is
  4. Fix it and test it.

some common errors

list('a', 'b', )
#> Error in list("a", "b", ) : argument 3 is empty

df$x
#> Error in df$x : object of type 'closure' is not subsettable

likely culprits

syntax issues

  • parentheses mismatch
  • missing (or extra) comma
  • [[]] vs. []
  • == vs. =
  • floating point numbers being tricky
    • examples: .1 + .05 == .15
  • unexpected vector recycling; vectorization not working properly
  • elementwise comparison (=> use identical() or all.equal())
  • silent type conversions

logic issues

  • confusing variable or function names
  • giving unnamed function arguments in the wrong order
  • what you’ve written doesn’t do what you mean to
    • something was left out
    • the order of operations isn’t right
    • something extra is added
    • sometimes there are very small typos

scope issues

  • relying on a global variable and the global variable has changed
  • assuming that changing a value inside one function will change it elsewhere
  • confusing variables within a function with those from where the function was called

what if those still don’t fix it?

the print / message / warning method

insert print statements to help you verify 1) your understanding of what is happening and 2) that what you expect to be happening is happening.

simplify simplify simplify

  • reduce your unexpected behavior to the simplest possible case

google your error message if you have no idea what it means

example of how googling your error can be helpful

traceback

f <- function(a) g(a)
g <- function(b) h(b)
h <- function(c) i(c)
i <- function(d) {
  if (!is.numeric(d)) {
    stop("`d` must be numeric")
  }
  d + 10
}
f("a")
screenshot of a traceback

apply the scientific method to bugs

hypothesize, test, repeat – and keep track of how things are going.

it’s quite easy to work yourself into a panic over a bug, so make sure to take breaks.

use the debugger

screenshot of a traceback

use the debugger

screenshot of a traceback

use the debugger

screenshot of a traceback

all of that still doesn’t work?

  • restart your R session and start from scratch
  • try re-writing the code
  • try talking to a friend / colleague
  • try the rubber ducky method
  • take a break
  • take notes on your approaches and share with colleagues
  • share a reprex on StackOverflow / the R4DS Slack

resources