This repository has been archived by the owner on Mar 27, 2019. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathREADME.Rmd
139 lines (103 loc) · 3.71 KB
/
README.Rmd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
```{r, setup, echo = FALSE, message = FALSE}
knitr::opts_chunk$set(
comment = "#>",
tidy = FALSE,
error = FALSE,
fig.width = 8,
fig.height = 8)
```
# tamper
> Easier Debugging of `magrittr` Pipes
[![Linux Build Status](https://travis-ci.org/gaborcsardi/tamper.svg?branch=master)](https://travis-ci.org/gaborcsardi/tamper)
[![Windows Build status](https://ci.appveyor.com/api/projects/status/github/gaborcsardi/tamper?svg=true)](https://ci.appveyor.com/project/gaborcsardi/tamper)
[![](http://www.r-pkg.org/badges/version/tamper)](http://www.r-pkg.org/pkg/tamper)
[![CRAN RStudio mirror downloads](http://cranlogs.r-pkg.org/badges/tamper)](http://www.r-pkg.org/pkg/tamper)
One difficulty of
[`magrittr`](https://github.com/smbache/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.
## Installation
```{r eval = FALSE}
devtools::install_github("gaborcsardi/tamper")
```
## Rationale
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.
```r
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.
## Usage
```r
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.
```r
library(magrittr)
1:10 %>%
multiply_by(10) %>%
add(10) %>%
add("oh no!") %>%
subtract(5) %>%
divide_by(5)
```
You will see:
```r
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:
```r
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:
```r
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:
```r
Browse[1]> assign("value", value, envir = globalenv())
```
## Feedback
Please see our
[issue tracker](https://github.com/gaborcsardi/tamper/issues).
## License
MIT © [Gábor Csárdi](https://github.com/gaborcsardi).