test_that("constructor sets attributes", {
x <- new_vctr(1:4, class = "x", x = 1)
expect_equal(x, structure(1:4, class = c("x", "vctrs_vctr"), x = 1))
x <- new_vctr(1:4, class = "x", x = 1, inherit_base_type = TRUE)
expect_equal(x, structure(1:4, class = c("x", "vctrs_vctr", "integer"), x = 1))
})
test_that(".data must be a vector", {
expect_error(new_vctr(mean), "vector type")
})
test_that("attributes other than names are ignored", {
out <- new_vctr(structure(1, a = 1))
expect_null(attributes(out)$a)
})
test_that("default format method is internal", {
x <- new_vctr(1, class = "x")
expect_equal(format(x), format(x))
})
test_that("vctr class is proxied", {
expect_identical(vec_proxy(new_vctr(1:3)), new_vctr(1:3))
expect_identical(vec_proxy(new_vctr(as.list(1:3))), unclass(new_vctr(as.list(1:3))))
expect_true(vec_is(new_vctr(as.list(1:3))))
})
test_that("Can opt out of base type", {
x <- new_vctr(1, class = "x", inherit_base_type = FALSE)
expect_s3_class(x, c("x", "vctrs_vctr"), exact = TRUE)
})
test_that("base type is always set for lists", {
expect_s3_class(new_vctr(list()), "list")
})
test_that("cannot opt out of the base type with lists", {
expect_error(new_vctr(list(), inherit_base_type = FALSE), "must inherit from the base type")
})
test_that("data frames are not allowed", {
expect_error(new_vctr(mtcars), "can't be a data frame")
})
test_that("attributes must be named", {
expect_error(vec_set_attributes(1, list(1)), "must be named")
expect_error(vec_set_attributes(1, list(y = 1, 2)), "2 does not")
})
test_that("can strip all attributes without adding new ones", {
expect_equal(vec_set_attributes(structure(1, a = 1), NULL), 1)
})
test_that("`c.vctrs_vctr()` checks for default method arguments (#791)", {
expect_error(c(new_vctr(1), recursive = TRUE), "`recursive` must be")
expect_error(c(new_vctr(1), use.names = FALSE), "`use.names` must be")
})
# Cast/restore ------------------------------------------------------------
test_that("cast to NULL returns x", {
x <- new_vctr(1, class = "x")
expect_equal(vec_cast(NULL, x), NULL)
})
test_that("cast succeeds if attributes equal", {
x1 <- new_vctr(1, class = "x", a = 1, b = 2)
x2 <- new_vctr(2, class = "x", a = 1, b = 2)
expect_equal(vec_cast(x1, x2), x1)
expect_equal(vec_cast(x2, x1), x2)
})
test_that("and fails if attributes are different", {
x1 <- new_vctr(1, class = "x", a = 1, b = 2)
x2 <- new_vctr(2, class = "x", a = 2, b = 2)
expect_error(vec_cast(x1, x2), class = "vctrs_error_incompatible_type")
})
test_that("restoring to atomic vector of same type preserves attributes", {
x1 <- new_vctr(1, class = "x")
x2 <- new_vctr(2, class = "x")
expect_equal(vec_restore(2, x1), x2)
})
test_that("restoring to atomic vector of different type throws error", {
x1 <- new_vctr(1, class = "x")
expect_error(vec_restore("x", x1), class = "vctrs_error_incompatible_type")
})
test_that("base coercion methods mapped to vec_cast", {
x <- new_vctr(1, inherit_base_type = FALSE)
expect_error(as.logical(x), class = "vctrs_error_incompatible_type")
expect_error(as.integer(x), class = "vctrs_error_incompatible_type")
expect_error(as.logical(x), class = "vctrs_error_incompatible_type")
expect_error(as.double(x), class = "vctrs_error_incompatible_type")
expect_error(as.character(x), class = "vctrs_error_incompatible_type")
expect_error(as.Date(x), class = "vctrs_error_incompatible_type")
expect_error(as.POSIXct(x), class = "vctrs_error_incompatible_type")
expect_error(as.POSIXlt(x), class = "vctrs_error_incompatible_type")
expect_equal(as.list(x), list(x))
})
test_that("as.data.frame creates data frame", {
x <- new_vctr(1:3)
df <- as.data.frame(x)
expect_s3_class(df, "data.frame")
expect_equal(nrow(df), 3)
expect_named(df, "x")
})
test_that("as.data.frame on shaped vctrs doesn't bring along extra attributes", {
x <- new_vctr(1:3, foo = "bar", dim = c(3L, 1L))
df <- as.data.frame(x)
expect_null(attr(df, "foo", exact = TRUE))
})
test_that("as.data.frame2() unclasses input to avoid dispatch on as.data.frame()", {
x <- structure(1:2, dim = c(1L, 2L), dimnames = list("r1", c("c1", "c2")), class = "foo")
expect <- data.frame(c1 = 1L, c2 = 2L, row.names = "r1")
local_methods(as.data.frame.foo = function(x, ...) "dispatched!")
expect_identical(as.data.frame2(x), expect)
})
test_that("as.list() chops vectors", {
expect_identical(
as.list(new_vctr(1:3)),
list(new_vctr(1L), new_vctr(2L), new_vctr(3L))
)
x <- new_vctr(as.list(1:3))
expect_identical(as.list(x), as.list(1:3))
})
# equality + comparison + arith + math ---------------------------------------
test_that("equality functions remapped", {
x <- new_vctr(c(1, 1, NA), inherit_base_type = FALSE)
expect_error(x == 1, class = "vctrs_error_incompatible_type")
expect_error(x != 1, class = "vctrs_error_incompatible_type")
expect_equal(is.na(x), c(FALSE, FALSE, TRUE))
expect_true(anyNA(x))
expect_equal(unique(x), new_vctr(c(1, NA), inherit_base_type = FALSE))
expect_equal(duplicated(x), c(FALSE, TRUE, FALSE))
expect_true(anyDuplicated(x))
})
test_that("is.na<-() supported", {
x <- new_vctr(1:4)
is.na(x) <- c(FALSE, FALSE, TRUE, NA)
expect_identical(x, new_vctr(c(1:2, NA, 4L)))
x <- new_vctr(1:4)
is.na(x) <- TRUE
expect_identical(x, new_vctr(rep(NA_integer_, 4)))
x <- new_vctr(1:4)
is.na(x) <- c(2, 3)
expect_identical(x, new_vctr(c(1L, NA, NA, 4L)))
names <- c("a", "b", "c", "d")
x <- set_names(new_vctr(1:4), names)
is.na(x) <- c("d", "b", "b")
expect_identical(x, set_names(new_vctr(c(1L, NA, 3L, NA)), names))
x <- new_vctr(1:4)
expect_error(is.na(x) <- "x", "character names to index an unnamed vector")
expect_error(is.na(x) <- 5, class = "vctrs_error_subscript_oob")
})
test_that("comparison functions remapped", {
local_methods(
vec_proxy_compare.bizzaro = function(x, ...) -vec_data(x)
)
x1 <- new_vctr(c(1, 2), class = "bizzaro")
x2 <- new_vctr(2, class = "bizzaro")
expect_equal(order(x1), c(2L, 1L))
expect_equal(x1 < x2, c(FALSE, FALSE))
expect_equal(x1 <= x2, c(FALSE, TRUE))
expect_equal(x1 > x2, c(TRUE, FALSE))
expect_equal(x1 >= x2, c(TRUE, TRUE))
})
test_that("operators remapped", {
local_methods(
vec_arith.bizzaro = function(op, x, y) 1L
)
x <- new_vctr(c(1, 2), class = "bizzaro")
expect_equal(x + 1, 1L)
expect_equal(x - 1, 1L)
expect_equal(x * 1, 1L)
expect_equal(x / 1, 1L)
expect_equal(x ^ 1, 1L)
expect_equal(x %% 1, 1L)
expect_equal(x %/% 1, 1L)
expect_equal(x & 1, 1L)
expect_equal(x | 1, 1L)
expect_equal(!x, 1L)
expect_equal(+x, 1L)
expect_equal(-x, 1L)
})
test_that("math functions overridden", {
local_methods(
vec_math.bizzaro = function(fn, x, ...) vec_math_base(fn, 2L)
)
x <- new_vctr(c(1, NA), class = "bizzaro")
expect_equal(mean(x), 2L)
expect_equal(sum(x), 2L)
expect_equal(is.finite(x), TRUE)
expect_equal(is.infinite(x), FALSE)
expect_equal(is.nan(x), FALSE)
})
test_that("diff matches base R", {
local_methods(
vec_arith.vctrs_minus = function(op, x, y) vec_arith_base(op, x, y)
)
x1 <- cumsum(cumsum(1:10))
x2 <- new_vctr(x1, class = "vctrs_minus")
expect_equal(diff(x2), diff(x1))
expect_equal(diff(x2, lag = 2L), diff(x1, lag = 2L))
expect_equal(diff(x2, differences = 2L), diff(x1, differences = 2L))
expect_equal(diff(x2, lag = 11), x2[0L])
expect_equal(diff(x2, differences = 11), x2[0L])
})
test_that("na.omit() works and retains metadata", {
x <- new_vctr(c(a = 1, b = NA, c = 2))
result <- na.omit(x)
expect <- vec_slice(x, c(1, 3))
attr(expect, "na.action") <- structure(c(b = 2L), class = "omit")
expect_identical(result, expect)
})
test_that("na.omit() returns its input unchanged if there are no missing values", {
x <- new_vctr(c(a = 1, b = 2))
expect_identical(na.omit(x), x)
})
test_that("na.exclude() works and retains metadata", {
x <- new_vctr(c(a = 1, b = NA, c = 2))
result <- na.exclude(x)
expect <- vec_slice(x, c(1, 3))
attr(expect, "na.action") <- structure(c(b = 2L), class = "exclude")
expect_identical(result, expect)
})
test_that("na.fail() works", {
x <- new_vctr(c(a = 1, b = 2))
expect_identical(na.fail(x), x)
x <- new_vctr(c(a = 1, b = NA, c = 2))
expect_snapshot(error = TRUE, na.fail(x))
})
# names -------------------------------------------------------------------
test_that("`NA_character_` names are repaired to the empty string (#784)", {
expect_named(new_vctr(set_names(1, NA_character_)), "")
expect_named(new_vctr(set_names(1:2, c("a", NA))), c("a", ""))
})
test_that("the empty string is an allowed name (#784)", {
expect_named(new_vctr(set_names(1, "")), "")
expect_named(new_vctr(set_names(1:2, c("", "x"))), c("", "x"))
})
test_that("can not provide invalid names", {
x <- new_vctr(c(a = 1, b = 2))
expect_error(names(x) <- "x", "length")
expect_error(names(x) <- c("x", "y", "z"), "length")
expect_error(names(x) <- NULL, NA)
})
test_that("can set names to the empty string (#784)", {
x <- new_vctr(c(a = 1, b = 2))
names(x) <- c("", "")
expect_named(x, c("", ""))
names(x) <- c("", "x")
expect_named(x, c("", "x"))
})
test_that("setting names to `NA_character_` repairs to the empty string (#784)", {
x <- new_vctr(1:2)
names(x) <- c(NA_character_, NA_character_)
expect_named(x, c("", ""))
names(x) <- c("x", NA_character_)
expect_named(x, c("x", ""))
})
test_that("can use [ and [[ with names", {
local_methods(
vec_ptype2.vctrs_vctr.double = function(...) dbl(),
vec_ptype2.double.vctrs_vctr = function(...) dbl()
)
x <- new_vctr(c(a = 1, b = 2))
expect_equal(x["b"], new_vctr(c(b = 2)))
expect_equal(x[["b"]], new_vctr(2)) # [[ drops names
x[["c"]] <- 3
expect_equal(x[["c"]], new_vctr(3))
x["d"] <- 4
expect_equal(x[["d"]], new_vctr(4))
})
test_that("can use [ and [[ with names - list vctr", {
local_methods(
vec_ptype2.vctrs_vctr = function(...) list(),
vec_ptype2.list.vctrs_vctr = function(...) list()
)
y <- new_vctr(list(a = 1, b = 2))
y[["c"]] <- 3
expect_equal(y[["c"]], 3)
y["d"] <- list(4)
expect_equal(y[["d"]], 4)
})
test_that("can use [[<- to replace n-dimensional elements", {
local_methods(
vec_restore.vctrs_mtrx = function(x, to, ...) x,
vec_ptype2.double.vctrs_mtrx = function(...) dbl(),
vec_ptype2.vctrs_mtrx = function(...) dbl()
)
x <- new_vctr(rep(1, times = 4), dim = c(2, 2), class = "vctrs_mtrx")
x[[2, 2]] <- 4
expect_equal(x[[2, 2]], 4)
})
test_that("subsetting preserves attributes", {
x <- new_vctr(c(a = 1, b = 2))
attr(x, "extra") <- TRUE
y <- x[1]
expect_equal(attr(x, "extra"), TRUE)
})
test_that("$ inherits from underlying vector", {
x1 <- new_vctr(c(a = 1, b = 2))
expect_error(x1$a, "atomic vectors")
expect_error(x1$a <- 2, "atomic vectors")
x2 <- new_vctr(list(a = 1, b = 2))
expect_equal(x2$a, 1)
x2$a <- 10
expect_equal(x2$a, 10)
})
# unsupported/unimplemented operations --------------------------------------
test_that("can't touch protected attributes", {
x <- new_vctr(1:4)
expect_error(dim(x) <- c(2, 2), class = "vctrs_error_unsupported")
expect_error(dimnames(x) <- list("x"), class = "vctrs_error_unsupported")
expect_error(levels(x) <- "x", class = "vctrs_error_unsupported")
# It is expected that unimplemented `levels()` returns `NULL`
expect_null(levels(x))
# But it's ok to set names to NULL; this happens at least in vec_c
# and maybe elsewhere. We may need to back off on this level of
# strictness in the future
expect_error(names(x) <- NULL, NA)
})
test_that("summary is unimplemented", {
x <- new_vctr(1:4)
expect_error(summary(x), class = "vctrs_error_unimplemented")
})
# hidden class ------------------------------------------------------------
# We can't construct classes in test because the methods are not found
# when vctr generics call other generics. Instead we rely on a very simple
# class implemented in vctr.R
test_that("class preserved when subsetting", {
h <- (1:4)
expect_s3_class(h, "hidden")
expect_s3_class(h[1], "hidden")
expect_s3_class(h[[1]], "hidden")
expect_s3_class(rep(h[1], 2), "hidden")
expect_s3_class(as.list(h)[[1]], "hidden")
length(h) <- 3
expect_s3_class(h, "hidden")
})
test_that("RHS cast when using subset assign", {
()
h <- (1)
expect_error(h[[1]] <- "x", class = "vctrs_error_incompatible_type")
expect_error(h[1] <- "x", class = "vctrs_error_incompatible_type")
h[2] <- 1
expect_equal(h, (c(1, 1)))
h[[2]] <- 2
expect_equal(h, (c(1, 2)))
})
test_that("c passes on to vec_c", {
()
h <- (1)
expect_equal(c(h), h)
expect_equal(c(h, NULL), h)
expect_equal(c(h, 1), rep(h, 2))
expect_equal(c(h, h), rep(h, 2))
})
test_that("rbind does not fail with an unclear message (#1186)", {
# In general, vec_rbind() should be preferred. In many cases rbind() does
# the right thing, this test exists to alert us if this changes in the future.
skip_on_cran()
()
h <- (1)
# A failure in levels() for vctrs_vctr classes was the underlying issue.
expect_null(levels(h))
df <- data_frame(h = h)
expect_equal(rbind(df), df)
expect_equal(rbind(df, NULL), df)
expect_equal(rbind(df, data_frame(h = 1)), unrownames(df[c(1, 1), , drop = FALSE]))
expect_equal(rbind(df, df), unrownames(df[c(1, 1), , drop = FALSE]))
# An example where the result differs, to alert us if the rbind() contract
# changes
expect_equal(rbind(data_frame(h = 1), df), data_frame(h = c(1, 1)))
})
test_that("summaries preserve class", {
h <- (c(1, 2))
expect_equal(sum(h), (3))
expect_equal(mean(h), (1.5))
})
test_that("methods using vec_proxy_compare agree with base", {
h <- (c(1:10))
h_na <- (c(NA, 1:10))
expect_agree <- function(f, x, na.rm = FALSE) {
f <- enexpr(f)
expect_equal(vec_data((!!f)(x, na.rm = na.rm)), (!!f)(vec_data(x), na.rm = na.rm))
}
expect_agree(min, h)
expect_agree(max, h)
expect_agree(range, h)
expect_agree(min, h_na)
expect_agree(max, h_na)
expect_agree(range, h_na)
expect_agree(min, h_na, na.rm = TRUE)
expect_agree(max, h_na, na.rm = TRUE)
expect_agree(range, h_na, na.rm = TRUE)
})
test_that("can put in data frame", {
h <- (1:4)
expect_named(as.data.frame(h), "h")
expect_named(data.frame(x = h), "x")
})
test_that("base coercions default to vec_cast", {
()
h <- (1)
expect_error(as.character(h), class = "vctrs_error_incompatible_type")
expect_error(as.integer(h), class = "vctrs_error_incompatible_type")
expect_error(generics::as.factor(h), class = "vctrs_error_incompatible_type")
expect_error(generics::as.ordered(h), class = "vctrs_error_incompatible_type")
expect_error(generics::as.difftime(h), class = "vctrs_error_incompatible_type")
expect_equal(as.logical(h), TRUE)
expect_equal(as.double(h), 1)
})
test_that("default print and str methods are useful", {
h <- (1:4)
expect_snapshot(h)
expect_snapshot(h[0])
expect_snapshot(str(h))
})
test_that("default print method shows names", {
h <- (c(A = 1, B = 2, C = 3))
expect_snapshot(h)
})
test_that("can't transpose", {
h <- (1:4)
expect_error(t(h), class = "vctrs_error_unsupported")
})
test_that("shaped vctrs can be cast to data frames", {
x <- new_vctr(1:4, dim = 4)
expect_identical(as.data.frame(x), data.frame(V1 = 1:4))
x <- new_vctr(1:4, dim = c(2, 2))
expect_identical(as.data.frame(x), data.frame(V1 = 1:2, V2 = 3:4))
})
# slicing -----------------------------------------------------------------
test_that("additional subscripts are handled (#269)", {
new_2d <- function(.data, dim) {
vctrs::new_vctr(.data, dim = dim, class = "vctrs_2d")
}
x <- new_2d(c(1, 2), dim = c(2L, 1L))
expect_identical(x[1], new_2d(1, dim = c(1, 1)))
expect_identical(x[1, 1], new_2d(1, dim = c(1, 1)))
expect_identical(x[, 1], new_2d(c(1, 2), dim = c(2, 1)))
})
# summary generics --------------------------------------------------------
test_that("na.rm is forwarded to summary generics", {
x <- new_vctr(dbl(1, 2, NA))
expect_identical(mean(x, na.rm = FALSE), new_vctr(dbl(NA)))
expect_identical(mean(x, na.rm = TRUE), new_vctr(1.5))
expect_identical(min(x, na.rm = FALSE), new_vctr(dbl(NA)))
expect_identical(min(x, na.rm = TRUE), new_vctr(1))
expect_identical(max(x, na.rm = FALSE), new_vctr(dbl(NA)))
expect_identical(max(x, na.rm = TRUE), new_vctr(2))
x <- new_vctr(lgl(TRUE, NA))
expect_identical(all(x, na.rm = FALSE), lgl(NA))
expect_identical(all(x, na.rm = TRUE), TRUE)
})
test_that("Summary generics behave identically to base for empty vctrs (#88)", {
expect_warning(
expect_identical(
new_vctr(max(numeric())),
max(new_vctr(numeric()))
)
)
expect_warning(
expect_identical(
new_vctr(min(numeric())),
min(new_vctr(numeric()))
)
)
expect_identical(
new_vctr(range(1)),
range(new_vctr(1))
)
expect_identical(
new_vctr(prod(numeric())),
prod(new_vctr(numeric()))
)
expect_identical(
new_vctr(sum(numeric())),
sum(new_vctr(numeric()))
)
expect_identical(
new_vctr(cummax(numeric())),
cummax(new_vctr(numeric()))
)
expect_identical(
new_vctr(cummin(numeric())),
cummin(new_vctr(numeric()))
)
expect_identical(
new_vctr(cumprod(numeric())),
cumprod(new_vctr(numeric()))
)
expect_identical(
new_vctr(cumsum(numeric())),
cumsum(new_vctr(numeric()))
)
expect_identical(
new_vctr(mean(numeric())),
mean(new_vctr(numeric()))
)
})
test_that("generic predicates return logical vectors (#251)", {
x <- new_vctr(c(1, 2))
expect_identical(is.finite(x), c(TRUE, TRUE))
expect_identical(is.infinite(x), c(FALSE, FALSE))
expect_identical(is.nan(x), c(FALSE, FALSE))
x <- new_vctr(TRUE)
expect_identical(any(x), TRUE)
expect_identical(all(x), TRUE)
})
test_that("xtfrm() converts logical types to integer", {
expect_identical(xtfrm(new_vctr(c(TRUE, FALSE, NA), foo = "bar")), c(1L, 0L, NA))
})
test_that("xtfrm() unwraps integer and double atomic types", {
expect_identical(xtfrm(new_vctr(1:3, foo = "bar")), 1:3)
expect_identical(xtfrm(new_vctr(1:3 + 0, foo = "bar")), 1:3 + 0)
})
test_that("xtfrm() works with character subclass", {
expect_identical(xtfrm(new_vctr(chr())), int())
})
test_that("xtfrm() maintains ties when falling through to vec_rank() (#1354)", {
x <- new_vctr(c("F", "F", "M", "A", "M", "A"))
expect_identical(xtfrm(x), c(2L, 2L, 3L, 1L, 3L, 1L))
})
test_that("xtfrm() propagates NAs when falling through to vec_rank()", {
x <- new_vctr(c("F", NA))
expect_identical(xtfrm(x), c(1L, NA))
})
test_that("xtfrm() uses C locale ordering with character proxies", {
x <- new_vctr(c("A", "a", "B"))
expect_identical(xtfrm(x), c(1L, 3L, 2L))
})
test_that("xtfrm() works on rcrd types", {
x <- new_rcrd(list(x = c(1, 2, 1, NA), y = c(2, 1, 1, NA)))
expect_identical(xtfrm(x), c(2L, 3L, 1L, NA))
})
test_that("Summary generics behave as expected if na.rm = TRUE and all values are NA (#1357)", {
expect_identical(min(new_vctr(NA_real_), na.rm = TRUE), new_vctr(Inf))
expect_identical(max(new_vctr(NA_real_), na.rm = TRUE), new_vctr(-Inf))
expect_identical(range(new_vctr(NA_real_), na.rm = TRUE), new_vctr(c(Inf, -Inf)))
expect_identical(min(new_vctr(NA_integer_), na.rm = TRUE), new_vctr(NA_integer_))
expect_identical(max(new_vctr(NA_integer_), na.rm = TRUE), new_vctr(NA_integer_))
expect_identical(range(new_vctr(NA_integer_), na.rm = TRUE), new_vctr(c(NA_integer_, NA_integer_)))
expect_identical(min(new_vctr(NA_character_), na.rm = TRUE), new_vctr(NA_character_))
expect_identical(max(new_vctr(NA_character_), na.rm = TRUE), new_vctr(NA_character_))
expect_identical(range(new_vctr(NA_character_), na.rm = TRUE), new_vctr(c(NA_character_, NA_character_)))
expect_identical(min(new_vctr(NA), na.rm = TRUE), new_vctr(NA))
expect_identical(max(new_vctr(NA), na.rm = TRUE), new_vctr(NA))
expect_identical(range(new_vctr(NA), na.rm = TRUE), new_vctr(c(NA, NA)))
})
test_that("Summary generics behave as expected for empty vctrs (#1357)", {
expect_identical(min(new_vctr(numeric()), na.rm = TRUE), new_vctr(Inf))
expect_identical(max(new_vctr(numeric()), na.rm = TRUE), new_vctr(-Inf))
expect_identical(range(new_vctr(numeric()), na.rm = TRUE), new_vctr(c(Inf, -Inf)))
expect_identical(min(new_vctr(integer()), na.rm = TRUE), new_vctr(NA_integer_))
expect_identical(max(new_vctr(integer()), na.rm = TRUE), new_vctr(NA_integer_))
expect_identical(range(new_vctr(integer()), na.rm = TRUE), new_vctr(c(NA_integer_, NA_integer_)))
expect_identical(min(new_vctr(character()), na.rm = TRUE), new_vctr(NA_character_))
expect_identical(max(new_vctr(character()), na.rm = TRUE), new_vctr(NA_character_))
expect_identical(range(new_vctr(character()), na.rm = TRUE), new_vctr(c(NA_character_, NA_character_)))
expect_identical(min(new_vctr(logical()), na.rm = TRUE), new_vctr(NA))
expect_identical(max(new_vctr(logical()), na.rm = TRUE), new_vctr(NA))
expect_identical(range(new_vctr(logical()), na.rm = TRUE), new_vctr(c(NA, NA)))
})
test_that("anyNA(recursive = TRUE) works with lists (#1278)", {
x <- list_of(1:4, c(2, NA, 5))
expect_false(anyNA(x))
expect_true(anyNA(x, recursive = TRUE))
x <- new_vctr(list(1:4, list(c(2, NA, 5))))
expect_false(anyNA(x))
expect_true(anyNA(x, recursive = TRUE))
})
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.