knitr::opts_chunk$set( collapse = TRUE, comment = "#>", fig.path = "man/figures/README-", out.width = "100%" )
The {boomer} package provides debugging tools that let you inspect the intermediate results of a call. The output looks as if we explode a call into its parts hence the name.
boom()
prints the intermediate results of a call or a code chunk.rig()
creates a copy of a function which will display the intermediate
results of all the calls of it body.rig_in_namespace()
rigs a namespaced function in place, so its always
verbose even when called by other existing functions. It is especially handy
for package development.Install CRAN version with:
install.packages("boomer")
Or development version with:
remotes::install_github("moodymudskipper/boomer")
boom()
library(boomer) boom(1 + !1 * 2)
boom(subset(head(mtcars, 2), qsec > 17))
You can use boom()
with {magrittr} pipes or base R pipes: just pipe to boom()
at the end of a pipe chain.
library(magrittr) mtcars %>% head(2) %>% subset(qsec > 17) %>% boom()
If a call fails, {boomer} will print intermediate outputs up to the occurrence of the error, it can help with debugging:
"tomato" %>% substr(1, 3) %>% toupper() %>% sqrt() %>% boom()
boom()
features optional arguments :
clock
: set to TRUE
to see how long each step (in isolation!) took to run.
print
: set to a function such as str
to change what is printed (see ?boom
to see how to print differently depending on class). Useful alternatives would be dplyr::glimpse
of invisible
(to print nothing).
One use case is when the output is too long.
boom(lapply(head(cars), sqrt), clock = TRUE, print = str)
boom()
also works works on loops and multi-line expression.
boom(for(i in 1:3) paste0(i, "!"))
rig()
rig()
a function in order to boom()
its body, its arguments are printed
by default when they're evaluated.
hello <- function(x) { if(!is.character(x) | length(x) != 1) { stop("`x` should be a string") } paste0("Hello ", x, "!") } rig(hello)("world")
rig_in_namespace()
rig()
creates a copy of a function, but when developing a package we might
want to rig a function in place so it has a verbose output when called by other
functions. For this we can use rig_in_namespace()
.
For instance you might have these functions in a package :
cylinder_vol <- function(r, h) { h * disk_area(r) } disk_area <- function(r) { pi * r^2 }
cylinder_vol
depends on disk_area
, call devtools::load_all()
then rig_in_namespace()
on both
and enjoy the detailed output:
devtools::load_all() rig_in_namespace(cylinder_vol, disk_area) cylinder_vol(3,10)
boom_on()
and boom_off()
While debugging a function, call boom_on()
and all subsequent calls will be boomed,
call boom_off()
to return to standard debugging.
boom_shinyApp()
A very experimental feature that allows you to rig the reactives of a shiny app. See vignette("shiny", "boomer")
for more information.
For the following app, saved in a proper project/package:
histogramUI <- function(id) { tagList( selectInput(NS(id, "var"), "Variable", choices = names(mtcars)), numericInput(NS(id, "bins"), "bins", value = 10, min = 1), plotOutput(NS(id, "hist")) ) } histogramServer <- function(id) { moduleServer(id, function(input, output, session) { data <- reactive(mtcars[[input$var]]) output$hist <- renderPlot({ hist(data(), breaks = input$bins, main = input$var) }, res = 96) }) } ui <- fluidPage( histogramUI("hist1") ) server <- function(input, output, session) { histogramServer("hist1") }
The output of boom_shinyApp(ui, server)
will look like:
There will be issues, please report!
To avoid typing boom()
all the time you can use the provided addin named "Explode a call with boom()
":
just attribute a key combination to it (I use ctrl+shift+alt+B on windows), select the
call you'd like to explode and fire away!
Several options are proposed to weak he printed output of {boomer}'s functions
and addin, see ?boomer
to learn about them.
In particular on some operating systems {boomer}'s functions' output might
not always look good in markdown report or reprexes.
It's due to how he system handles UTF-8 characters. In this case
one can use options(boomer.safe_print = TRUE)
for a more satisfactory input.
{boomer} prints the output of intermediate steps as they are executed, and
thus doesn't say anything about what isn't executed, it is in contrast with
functions like lobstr::ast()
which return the parse tree.
Thanks to @data_question for suggesting the name {boomer} on twitter.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.