-
Notifications
You must be signed in to change notification settings - Fork 129
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Define responsibilities of new_tibble() #332
Changes from 10 commits
a0bb75d
4573a61
56cfb86
dc89618
558a406
eb64ffa
0c59c12
5103cc1
a696bde
cd1f1b0
d865998
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,14 +1,55 @@ | ||
#' Constructor | ||
#' | ||
#' Creates a subclass of a tibble. | ||
#' This function is mostly useful for package authors that implement subclasses | ||
#' of a tibble, like \pkg{sf} or \pkg{tibbletime}. | ||
#' | ||
#' @param x A tibble-like object | ||
#' @param ... Passed on to [structure()] | ||
#' @param nrow The number of rows, guessed from the data by default | ||
#' @param subclass Subclasses to assign to the new object, default: none | ||
#' @export | ||
new_tibble <- function(x, ..., subclass = NULL) { | ||
#' @examples | ||
#' new_tibble(list(a = 1:3, b = 4:6)) | ||
#' new_tibble(list(), nrow = 150, subclass = "my_tibble") | ||
#' | ||
#' \dontrun{ | ||
#' # All columns must be the same length: | ||
#' new_tibble(list(a = 1:3, b = 4.6)) | ||
#' | ||
#' # The length must be consistent with the nrow argument if available: | ||
#' new_tibble(list(a = 1:3, b = 4:6), nrow = 2) | ||
#' } | ||
new_tibble <- function(x, ..., nrow = NULL, subclass = NULL) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this needs a bit more documentation, i.e.:
|
||
#' @details | ||
#' `x` must be a named (or empty) list, but the names are not currently | ||
#' checked for correctness. | ||
stopifnot(is.list(x)) | ||
if (length(x) == 0) names(x) <- character() | ||
stopifnot(has_nonnull_names(x)) | ||
|
||
#' @details | ||
#' The `...` argument allows adding more attributes to the subclass. | ||
x <- update_tibble_attrs(x, ...) | ||
x <- set_tibble_class(x, subclass = subclass) | ||
|
||
#' @details | ||
#' The `row.names` attribute will be computed from the `nrow` argument, | ||
#' overriding any existing attribute of this name in `x` or in the `...` | ||
#' arguments. | ||
#' If `nrow` is `NULL`, the number of rows will be guessed from the data. | ||
if (is.null(nrow)) nrow <- guess_nrow(x) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The comment doesn't seem right to me - I think it should just be "set row names" (in which case you can just remove it) |
||
attr(x, "row.names") <- .set_row_names(nrow) | ||
|
||
#' The `new_tibble()` constructor makes sure that the `row.names` attribute | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why doesn't this need |
||
#' is consistent with the data before returning. | ||
validate_nrow(x) | ||
|
||
#' @details | ||
#' The `class` attribute of the returned object always consists of | ||
#' `c("tbl_df", "tbl", "data.frame")`. If the `subclass` argument is set, | ||
#' it will be prepended to that list of classes. | ||
class(x) <- c(subclass, "tbl_df", "tbl", "data.frame") | ||
|
||
x | ||
} | ||
|
||
|
@@ -32,7 +73,23 @@ update_tibble_attrs <- function(x, ...) { | |
x | ||
} | ||
|
||
set_tibble_class <- function(x, subclass = NULL) { | ||
class(x) <- c(subclass, "tbl_df", "tbl", "data.frame") | ||
x | ||
guess_nrow <- function(x) { | ||
if (!is.null(.row_names_info(x, 0L))) .row_names_info(x, 2L) | ||
else if (length(x) == 0) 0L | ||
else NROW(x[[1L]]) | ||
} | ||
|
||
validate_nrow <- function(x) { | ||
# Validate column lengths, don't recycle | ||
lengths <- map_int(x, NROW) | ||
first <- .row_names_info(x, 2L) | ||
|
||
bad_len <- lengths != first | ||
if (any(bad_len)) { | ||
invalid_df_msg( | ||
paste0("must be length ", first, ", not "), x, bad_len, lengths[bad_len] | ||
) | ||
} | ||
|
||
invisible(x) | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a little subtle without a comment