Chapter 22 Debugging

Resources on debugging:

22.3 Lazy evaluation

rlang::last_trace() in the example doesn’t show anything informative, really. What is this function and when is it helpful?

It’s weird how in the book it says > Error: Can’t show last error because no error was recorded yet

That’s not what you get in RStudio, but is what you get with a reprex….

rlang::last_trace prints the traceback/call stack in reverse order, but more visibly displays branching AST:

#> Error: Oops!
#> Backtrace:
#>  1. rlang::with_abort(f(j()))
#>  7. global::j()
#>  8. global::k()
#> Error: Oops!
#> Backtrace:
#>  1. rlang::with_abort(f(j()))
#>  7. global::j()
#>  8. global::k()
#> <error/rlang_error>
#> Oops!
#> Backtrace:
#> x
#> 1. +-rlang::with_abort(f(j()))
#> 2. | \-base::withCallingHandlers(...)
#> 3. +-global::f(j())
#> 4. | \-global::g(a)
#> 5. |   \-global::h(b)
#> 6. |     \-global::i(c)
#> 7. \-global::j()
#> 8.   \-global::k()

The errors render like how it does in the book if I use a reprex, but I get more verbose output in RStudio, which I’ve copy-pasted above. Not sure if this has to do with my options and/or RStudio settings. But i think it’s useful to see how rlang::last_trace() prints more detailed output like this.

22.4.1 broswer

Can we create a video or gif using browser?

22.4.2.1 Breakpoints

There are a few unusual situations in which breakpoints will not work

What are these fringe situations?

They don’t work in non-saved files, or Shiny Apps

Can we create a video or gif using breakpoints?

22.1 22.4.2.2 recover

Can we create a video or gif using recover?

22.4.2.3 debug

Can we create a video or gif using debug?

Can we create a video or gif using utils::setBreakpoint?

22.5 Non-interactive debugging

Sometimes callr::r(f, list(1, 2)) can be useful;

What is this? When is it useful?

This statement really seems not fully fleshed out… it provides no explanation what the function is and why it is “helpful” and he demonstrates it with the use of some anonymous function

Debug Pipe

# debug pipe
`%d>%` <- function(e1, e2) {
  x <- as.character(substitute(e2)[[1]])
  debugonce(get(x, parent.frame()))
  eval(substitute(e1 %>% e2), parent.frame())
}

mtcars %>% 
  select(mpg, cyl) %d>%   # debug group_by
  group_by(cyl) %>% 
  summarise(mpg = mean(mpg))

mtcars %>% 
  select(mpg, cyl) %d>%   # debug group_by
  group_by(cyl) %>% 
  summarise(mpg = mean(mpg))
#> debugging in: group_by(., cyl)
#> debug: {
#>     UseMethod("group_by")
#> }
#> debug: UseMethod("group_by")
#> debugging in: group_by.data.frame(., cyl)
#> debug: {
#>     groups <- group_by_prepare(.data, ..., .add = .add)
#>     grouped_df(groups$data, groups$group_names, .drop)
#> }
#> debug: groups <- group_by_prepare(.data, ..., .add = .add)
#> debug: grouped_df(groups$data, groups$group_names, .drop)
#> exiting from: group_by.data.frame(., cyl)
#> exiting from: group_by(., cyl)
#> `summarise()` ungrouping output (override with `.groups` argument)
#> # A tibble: 3 x 2
#>     cyl   mpg
#>   <dbl> <dbl>
#> 1     4  26.7
#> 2     6  19.7
#> 3     8  15.1

22.2 Edic Code from Another function

library(ggplot2)
# imagine we want to edit ggplot2::aes
# copied from the console and then edited
aes <- function (x, y, ...) 
{
  message("In my new aes") #added this
  exprs <- enquos(x = x, y = y, ..., .ignore_empty = "none") # changed .ignore_empty
  aes <- new_aes(exprs, env = parent.frame())
  rename_aes(aes)
}
# crap!  My function doesn't know how to find the non-exported ggplot2 functions
ggplot(mtcars) + aes(x = mpg, y = cyl) + geom_point()
#> In my new aes
#> Error in new_aes(exprs, env = parent.frame()): could not find function "new_aes"
# we can fix that!
environment(aes) <- asNamespace("ggplot2")
# success!
ggplot(mtcars) + aes(x = mpg, y = cyl) + geom_point()
#> In my new aes
![](https://i.imgur.com/GSYX1sa.png)

Bonus tip

Be careful if you have variables named f n s or c while debugging. I very often will want to investigate them by just running e.g. > f in the console, expecting it to print f. but instead it finishes the current loop. print(f) instead!