While debugging a Redditor's question I came across an issue I've distilled here.
library(tibble)
tib_works <- tibble(x = NULL, y = NULL, z = NULL)
tib_fails <- tibble(x = c(), y = c(), z = c())
str(tib_works)
#> tibble [0 x 0] (S3: tbl_df/tbl/data.frame)
#> Named list()
str(tib_fails)
#> tibble [0 x 3] (S3: tbl_df/tbl/data.frame)
#> $ x: NULL
#> $ y: NULL
#> $ z: NULL
tib_works
#> # A tibble: 0 x 0
tib_fails
#> Error: Internal error in `vec_slice_impl()`: Unexpected `NULL`.
rlang::last_trace()
<error/rlang_error>
Internal error in `vec_slice_impl()`: Unexpected `NULL`.
Backtrace:
x
1. +-(function (x, ...) ...
2. \-pillar:::print.tbl(x)
3. +-base::writeLines(format(x, width = width, ..., n = n, n_extra = n_extra))
4. +-base::format(x, width = width, ..., n = n, n_extra = n_extra)
5. \-pillar:::format.tbl(x, width = width, ..., n = n, n_extra = n_extra)
6. \-pillar::tbl_format_setup(x, width = width, ..., n = n, max_extra_cols = n_extra)
7. +-pillar:::tbl_format_setup_(x, width, ..., n = n, max_extra_cols = max_extra_cols)
8. \-pillar:::tbl_format_setup.tbl(x, width, ..., n = n, max_extra_cols = max_extra_cols)
9. \-pillar:::df_head(x, n)
10. \-pillar:::vec_head(as.data.frame(x), n)
11. \-vctrs::vec_slice(x, seq_len(n))
12. \-(function () ...
df1 <- data.frame(x = NULL, y = NULL, z = NULL)
df2 <- data.frame(x = c(), y = c(), z = c())
identical(df1, df2)
#> [1] TRUE
Created on 2021-06-13 by the reprex package (v2.0.0)
Setting aside the larger issues that this is, to say the least, poor form, not doing what they intend, and would invariably lead to other issues immediately thereafter, is this the intended and desired behaviour of tibble()?
A clear analogy here would be to treat this like a patient telling their doctor "it hurts when I do this," and respond, "well, stop doing that! But, in the interest of helping novices should tibble() here:
- Throw an error.
- Throw a warning.
- Behave similarly to
data.frame() and produce identical objects in both cases.
- Do nothing differently,
tibble() is working as intended. This is a PEBCAK situation.
Alternately, should an error be thrown further up the chain somewhere in pillar, perhaps in pillar:::format.tbl() where an error message more relevant to the user's input could be generated?
While debugging a Redditor's question I came across an issue I've distilled here.
Created on 2021-06-13 by the reprex package (v2.0.0)
Setting aside the larger issues that this is, to say the least, poor form, not doing what they intend, and would invariably lead to other issues immediately thereafter, is this the intended and desired behaviour of
tibble()?A clear analogy here would be to treat this like a patient telling their doctor "it hurts when I do this," and respond, "well, stop doing that! But, in the interest of helping novices should
tibble()here:data.frame()and produce identical objects in both cases.tibble()is working as intended. This is a PEBCAK situation.Alternately, should an error be thrown further up the chain somewhere in pillar, perhaps in
pillar:::format.tbl()where an error message more relevant to the user's input could be generated?