Section 10 Function: Debugging

10.1 Debugging tool

Function Explanation
traceback() prints out the function call stack after an error occurs; does nothing if there is no error
debug() flags a function for debug mode which allows to step through execution of a function one line at a time
undebug() to take off the debug mode flags from a function
debugonce() flags a function for debug mode only once; the function does not need undebug after it runs once.
browser() suspends the execution of a function wherever it is called and puts the function in debug mode
trace() allows you to insert debugging code into a function a specific places
recover() allows to modify the error behavior so that you can browse the function call stack


In the Debug mode, you can move around the function:

  • Type n to execute the next line of code (RStudio: Press Enter or F10 or the relevant debug toolbar icon)

  • Type s to step into the current function call (RStudio: Press Shift+F4 or the relevant debug toolbar icon)

  • Type c to execute remaining of the current function or loop (RStudio: Press Shift+F6 or the relevant debug toolbar icon)

  • Type c to continue the execution until the next breakpoint is encountered (RStudio: Press Shift+F5 or the relevant debug toolbar icon)

  • Type Q to stop and exit the debug mode (RStudio: Press Shift+F8 or the relevant debug toolbar icon)

10.2 Example 1

fn <- function(x, b){
  cat('\nFunction begins...\n')
  for(i in 1:length(x)){
    cat('\n\nNumber: ', x[i])
    xp <- x[i] ^ b
    cat('\nPower: ', xp)
    xl <- log(x[i], base = b)
    cat('\nLog: ', xl)
  }
  cat('\n\nFunction ends...\n')
}


# Execute the function

x <- c(1, 4, 0, -5, 10)


# Without debugging

fn(x, 2)


# With debugging tools

debug(fn)
fn(x, 2)
undebug(fn)


# Debug once

debugonce(fn)


10.3 Example 2

fn_N_excl_NA <- function(x){
  return(sum(!is.na(x)))
}

fnAM <- function(x, ...){
  # n <- fn_N_excl_NA(x)
  # browser()
  xbar <- sum(x, ...) / n2
  return(xbar)
}

fnSummary <- function(x,...){
  n1 <- length(x)
  n2 <- fn_N_excl_NA(x)
  AM <- fnAM(x,...)
  Out <- list(N=n1, N_excl_NA=n2, AM=AM)
  return(Out)
}


x <- c(1:5, NA)

fnSummary(x, na.rm = TRUE)

traceback()

debug(fnSummary)
fnSummary(x)
undebug(fnSummary)


debugonce(fnSummary)
fnSummary(x)


10.4 Example 3

fn_N_excl_NA <- function(x){
    return(list(n = sum(!is.na(x))))
}

fnAM <- function(x, ...){
    n <- fn_N_excl_NA(x)
    # browser()
    xbar <- sum(x, ...) / n
    return(list(AM=xbar))
}

fnSummary <- function(x,...){
    n1 <- length(x)
    n2 <- fn_N_excl_NA(x)
    AM <- fnAM(x,...)
    Out <- list(N=n1, N_excl_NA=n2, AM=AM)
    return(Out)
}


x <- 1:5

fnSummary(x)

traceback()

debug(fnSummary)
fnSummary(x)
undebug(fnSummary)


debugonce(fnSummary)
fnSummary(x)