Yet another dark magic in R, empty argument
::opts_chunk$set(error = TRUE, collapse = TRUE) knitr
# install needed R packages
::update_packages(c('magrittr', 'testthat', 'tibble'), upgrade = TRUE)
remotes::install_github(c('krlmlr/deparse')) remotes
1 Beginning
在用 testthat 的时候发现了 dput()
真的很好用 1,就想找一下有没有把 tibble 转化成 tribble(...)
的函数。
结果 krlmlr 大人已经 实现 了:
<- tibble::tibble(x = 1:2, y = 2:1))
(df ## # A tibble: 2 x 2
## x y
## <int> <int>
## 1 1 2
## 2 2 1
::deparsec(df, as_tribble = TRUE)
deparse## tribble(
## ~x, ~y,
## 1L, 2L,
## 2L, 1L
## )
2 Development
继续逛了一下,看到有 好事者 还是不满意,觉得
tribble(
~mpg, ~cyl, ~disp, ~hp, ~drat, ~wt, ~qsec, ~vs, ~am, ~gear, ~carb,
21, 6, 160, 110, 3.9, 2.62, 16.46, 0, 1, 4, 4,
21, 6, 160, 110, 3.9, 2.875, 17.02, 0, 1, 4, 4
)
应该变成
::tribble(
tibble~mpg, ~cyl, ~disp, ~hp, ~drat, ~wt, ~qsec, ~vs, ~am, ~gear, ~carb
21, 6, 160, 110, 3.9, 2.62, 16.46, 0, 1, 4, 4
, 21, 6, 160, 110, 3.9, 2.875, 17.02, 0, 1, 4, 4
, )
他说的倒很有道理,后者使得调换不同的行变得很方便(前者把第1、2 行互换的话,需要给新的第1行加个,
,再从新的第2行删个,
)。但是 krlmlr 大人却提出:
tribble(
~a, ~b,
1, 2,
)
3 Climax
这就很有意思了,不会造成语法错误吗?
Thus I have a try myself, and find that empty argument means using parameter’s default value:
<- function(a=1,b=2) {
foobar print(a)
print(b)
}
foobar(3,)
## [1] 3
## [1] 2
foobar(,4)
## [1] 1
## [1] 4
foobar(3,4,)
## Error in foobar(3, 4, ): unused argument (alist())
Then I recall that I shouldn’t feel strange for this syntax:
1, ]
mtcars[ mtcars[ , ]
4 Epilogue
Understanding what happens, I start to think maybe I can write read_csv('', , 'cc')
instead of read_csv('', T, 'cc')
.
No, absolutely not!
If I really don’t want to type the T
, I’d better write read_csv('', col_types = 'cc')
.
Type 10 more character now, save a lot of times in the future.
例如你要检查
x
是不是期望的值,dput()
就可以告诉你什么样的 R 代码可以构造出期望的值:↩︎<- list() x $a = 1:3 x$b = c('a', 'b', 'c') x dput(x) ## list(a = 1:3, b = c("a", "b", "c")) ::expect_identical(x, list(a = 1:3, b = c("a", "b", "c"))) testthat::expect_identical(x[1], list(a = 1:3, b = c("a", "b", "c"))) testthat## Error: x[1] not identical to list(a = 1:3, b = c("a", "b", "c")). ## Length mismatch: comparison on first 1 components