knitr::opts_chunk$set( comment = "#>", tidy = FALSE, error = FALSE, fig.width = 8, fig.height = 8)
Easier Debugging of
magrittr
Pipes
One difficulty of
magrittr
pipes is that they make
debugging harder. If you don't always write correct code, and you use
pipes, then you'll find tamper
very useful. It is the magrittr
specific
alternative of the recover
function: when used with
options(error = tamper)
, after an error it displays the whole pipeline,
marks the place of the error, and helps saving the temporary results.
devtools::install_github("gaborcsardi/tamper")
Pipes make code more readable, but their internal non-standard evaluation sorcery interacts poorly with some development tools, in particular recover
, which helps inspecting the call stack after an error has occurred.
library(magrittr) options(error = recover) 1:10 %>% multiply_by(10) %>% add(10) %>% add("oh no!") %>% subtract(5) %>% divide_by(5) Error in add(., "oh no!") : non-numeric argument to binary operator Enter a frame number, or 0 to exit 1: 1:10 %>% multiply_by(10) %>% add(10) %>% add("oh no!") %>% subtract(5) %>% divide_by(5) 2: withVisible(eval(quote(`_fseq`(`_lhs`)), env, env)) 3: eval(quote(`_fseq`(`_lhs`)), env, env) 4: eval(expr, envir, enclos) 5: `_fseq`(`_lhs`) 6: freduce(value, `_function_list`) 7: function_list[[i]](value)
Doh? What does that mean? Only @smbache knows! What are mere mortals to do? tamper
to the rescue.
options(error = tamper::tamper)
Then, if you make a mistake in a pipeline, instead of the above meta-mumbo-jumbo produced by a clueless recover
,
tamper
is invoked and you can explore the data in the pipeline, and also save to a temporary variable.
library(magrittr) 1:10 %>% multiply_by(10) %>% add(10) %>% add("oh no!") %>% subtract(5) %>% divide_by(5)
You will see:
Error in add(., "oh no!") : non-numeric argument to binary operator Enter 0 to exit or choose: 1: Switch mode 2: Take me to the error 3: 1:10 %>% 4: multiply_by(., 10) %>% 5: add(., 10) %>% 6: -> add(., "oh no!") %>% 7: subtract(., 5) %>% 8: divide_by(., 5) Selection:
The stage with the error is clearly marked with an arrow. You can get to
the function in which the error happened by selecting 2
. (Unless it
is a primitive function, those are not in the call stack.)
If you select 6
, you can browse the frame that corresponds to the
pipeline stage in which the error happened:
Selection: 6 Called from: eval(substitute(expr), envir, enclos) Browse[1]> ls() [1] "function_list" "k" "value"
value
is the value of the .
dot variable, at the beginning
of the pipeline stage:
Browse[1]> value [1] 20 30 40 50 60 70 80 90 100 110
If you don't want to redo the initial part of the pipeline, you
can save value
to a global variable in your workspace:
Browse[1]> assign("value", value, envir = globalenv())
Please see our issue tracker.
MIT © Gábor Csárdi.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.