R/split-combine.R:34-39. After stripping a split equal to tf_domain(x)[1], splits may be numeric(0), and if (splits[length(splits)] == tf_domain(x)[2]) becomes if (logical(0)) → "argument is of length zero". Separately, include = "left" indexes end[1:(length(end) - 1)], which breaks when length(end) == 1.
Reproduce
library(tf)
x <- tf_rgp(2)
tf_split(x, splits = 0) # arg of length zero
tf_split(x, splits = tf_domain(x)) # also breaks
tf_split(x, splits = 0.5, include = "left") # single split, include = "left"
Fix
Guard the empty-splits case (return x wrapped in a length-1 list, or error explicitly). Use seq_len(length(end) - 1) instead of 1:(length(end) - 1). Document the include offset behavior — it's currently a multiple of get_resolution() (a heuristic power of ten) and can drop or keep grid points unexpectedly on fine grids.
Regression test
test_that("tf_split handles boundary and single-split inputs", {
x <- tf_rgp(2)
expect_no_error(tf_split(x, splits = 0))
expect_no_error(tf_split(x, splits = tf_domain(x)))
expect_no_error(tf_split(x, splits = 0.5, include = "left"))
expect_no_error(tf_split(x, splits = 0.5, include = "right"))
})
Found in the June-2026 ground-up review.
R/split-combine.R:34-39. After stripping a split equal totf_domain(x)[1],splitsmay benumeric(0), andif (splits[length(splits)] == tf_domain(x)[2])becomesif (logical(0))→ "argument is of length zero". Separately,include = "left"indexesend[1:(length(end) - 1)], which breaks whenlength(end) == 1.Reproduce
Fix
Guard the empty-
splitscase (returnxwrapped in a length-1 list, or error explicitly). Useseq_len(length(end) - 1)instead of1:(length(end) - 1). Document theincludeoffset behavior — it's currently a multiple ofget_resolution()(a heuristic power of ten) and can drop or keep grid points unexpectedly on fine grids.Regression test
Found in the June-2026 ground-up review.