Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/moodymudskipper/boomer
Debugging Tools to Inspect the Intermediate Steps of a Call
https://github.com/moodymudskipper/boomer
Last synced: 2 days ago
JSON representation
Debugging Tools to Inspect the Intermediate Steps of a Call
- Host: GitHub
- URL: https://github.com/moodymudskipper/boomer
- Owner: moodymudskipper
- Created: 2021-02-05T01:41:47.000Z (almost 4 years ago)
- Default Branch: master
- Last Pushed: 2024-09-14T08:41:45.000Z (3 months ago)
- Last Synced: 2024-09-14T19:37:12.441Z (3 months ago)
- Language: R
- Homepage: https://moodymudskipper.github.io/boomer/
- Size: 7.54 MB
- Stars: 134
- Watchers: 5
- Forks: 3
- Open Issues: 24
-
Metadata Files:
- Readme: README.Rmd
- Changelog: NEWS.md
Awesome Lists containing this project
- jimsghstars - moodymudskipper/boomer - Debugging Tools to Inspect the Intermediate Steps of a Call (R)
README
---
output: github_document
---[![R-CMD-check](https://github.com/moodymudskipper/boomer/workflows/R-CMD-check/badge.svg)](https://github.com/moodymudskipper/boomer/actions)
```{r, include = FALSE}
knitr::opts_chunk$set(
collapse = TRUE,
comment = "#>",
fig.path = "man/figures/README-",
out.width = "100%"
)
```# boomer
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.## Installation
Install CRAN version with:
``` r
install.packages("boomer")
```Or development version with:
``` r
remotes::install_github("moodymudskipper/boomer")
```## `boom()`
```{r, eval = FALSE}
library(boomer)
boom(1 + !1 * 2)
```![](man/figures/README-1.png)
```r
boom(subset(head(mtcars, 2), qsec > 17))
```![](man/figures/README-2.png)
You can use `boom()` with *{magrittr}* pipes or base R pipes: just pipe to `boom()` at the end of a pipe chain.
```{r, eval = FALSE}
library(magrittr)
mtcars %>%
head(2) %>%
subset(qsec > 17) %>%
boom()
```![](man/figures/README-3.png)
If a call fails, *{boomer}* will print intermediate outputs up to the occurrence of the error,
it can help with debugging:```{r, eval = FALSE}
"tomato" %>%
substr(1, 3) %>%
toupper() %>%
sqrt() %>%
boom()
```![](man/figures/README-4.png)
`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.
```{r, eval = FALSE}
boom(lapply(head(cars), sqrt), clock = TRUE, print = str)
```![](man/figures/README-5.png)
`boom()` also works works on loops and multi-line expression.
```r
boom(for(i in 1:3) paste0(i, "!"))
```![](man/figures/README-6.png)
## `rig()`
`rig()` a function in order to `boom()` its body, its arguments are printed
by default when they're evaluated.```{r, eval = FALSE}
hello <- function(x) {
if(!is.character(x) | length(x) != 1) {
stop("`x` should be a string")
}
paste0("Hello ", x, "!")
}
rig(hello)("world")
```![](man/figures/README-7.png)
## `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 :
```{r}
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:```{r, eval = FALSE}
devtools::load_all()
rig_in_namespace(cylinder_vol, disk_area)
cylinder_vol(3,10)
```![](man/figures/README-9.png)
## `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.![](man/figures/README-10.gif)
## `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:
```{r, eval = FALSE}
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:
![](man/figures/README-11.gif)
There will be issues, please report!
## Addin
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!## Options
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.## Notes
*{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](https://twitter.com/data_question/status/1356615026988179464).