Skip to content

Hygiene backlog: docs, exports, dead code, dependencies, duplication #260

@fabian-s

Description

@fabian-s

Grab-bag of small items from the June-2026 ground-up review. Each one is independently tractable; group as one-PR each or batch.

Docs that mislead or fail R CMD check

  • man/landmarks.Rd is \keyword{internal} (inherited from @keywords internal on shared @rdname blocks at R/landmarks.R:121,195,275) for an exported function tf_landmarks_extrema; \usage lists detect_landmarks/cluster_landmarks/build_landmark_matrix which are not exported → R CMD check WARNING. Split the topics.
  • man/vctrs.Rd self-renamed to vec_ptype2.tfd_mv.tfd_mv.Rd because the mv block now sorts first under @rdname vctrs — pkgdown URL break (reference/vctrs.htmlreference/vec_ptype2.tfd_mv.tfd_mv.html). Pin @name vctrs on the first-collated block.
  • R/data.R: gait says "Data is also include in the datasets package" — wrong, it's in fda. growth documents gender as "(boy/girl)" while the factor levels are female/male. None of the @format blocks mention that height/knee_angle/hip_angle are tfd columns — the point of shipping these data. "Data is also include" — grammar typo three times. gait says "39 boys" — fda says "39 children".
  • R/utils.R:209-216: unique_id() doc reads @returns "x turned into a list" (copy-pasted from ensure_list). Both have the description "See above." — there is no above.
  • man/tfmethods.Rd renders @param object as usual / @param ... dots literally.
  • man/tfviz.Rd has @param y documented as "for the x-axis...!" — cute but unhelpful; also "an tf object".
  • Missing @examples: man/plot.tf_mv.Rd, man/fpc_wsvd.Rd, man/converters-mv.Rd — flagship new pages with zero examples.

Exported plumbing that should be internal

  • ensure_list, unique_id (R/utils.R:193-216) — pure plumbing with broken docs; @keywords internal or unexport.
  • prep_plotting_arg — same.
  • Unprefixed exports: in_range/%inr% — at minimum add tf_ prefix or document why these are unprefixed.

coef.tfb strips names

R/methods.R:229-232: attributes(object) <- NULL strips names too. Save/restore.

Predicate duplication

R/methods.R:274-286: is_tfd_reg <- is_reg, is_tfd_irreg <- is_irreg — straight duplicates. Pick one spelling, deprecate the other.

Masking base/stats generics

R/summarize.R:117,133, R/depth.R:383,196: sd, var, rank, fivenum redefined as new generics — shadows stats/base for every session attaching tf. Additionally xtfrm.tf (R/depth.R:419-421) silently imposes a depth-based total order (MHI hard-coded) on sort()/order()/rank() — major semantic decision documented only in ?tf_order.

Recommendation: prefer tf_f* verbs (they exist); have xtfrm.tf warn on first use (rlang::warn(..., .frequency = "once")).

Dependency diet

  • mvtnorm used exactly once (rmvnorm in R/rng.R:123) — replace with a 4-line chol()-based sampler.
  • pracma used solely for savgol (R/smooth.R) — either inline (~10 lines) or move to Suggests + requireNamespace().
  • README claims "no tidyverse-dependencies" but DESCRIPTION imports purrr (a core tidyverse package, with an except list in R/tf-package.R). Soften the README claim or eventually replace purrr::map* with base lapply/vapply.

Dead code / coverage theater

  • R/globals.R: ~15 of 19 globalVariables() entries reference variables that no longer exist anywhere in R/ (leftover ggplot geoms now in tidyfun). Prune.
  • # nocov wraps the entire zoo_wrapper body (R/approx.R:2,12) — i.e. the implementation of all six tf_approx_* evaluators — and the whole savgol/rollmean branch of tf_smooth (R/smooth.R:81,117). # nocov is for genuinely unreachable code, not "the report looks better this way". Bug #__ (duplicated arg positions) lives in this hidden region.
  • No test files at all for: graphics.R, plot-mv.R, smooth.R, approx.R, math.R, soft-impute-svd.R. _snaps/ exists and is empty — zero expect_snapshot() in a package with this much bespoke print/format code.

Duplication backlog (mechanical, low-risk)

  • NA-restoration is implemented 4× (restore_na_entries R/calculus.R:99, tfb_na_result R/ops.R:352-359 with a duplicated names(result) <- names(eval) at lines 356 and 358, inline blocks in Math.tfb and 3× in ops.R).
  • tfd_op_numeric / numeric_op_tfd / the three tfb_op_* are ~90% copy-paste; the acknowledged TODO is at R/ops.R:330.
  • Eight cum* stubs (R/summarize.R:251-298) collapsible to one Math-style dispatcher.
  • tf_fmax/tf_fmin/tf_fmedian (R/fwise.R:58-83) are one factory.
  • The 1 * NA * x[1] make-an-NA-function idiom appears 3× (R/summarize.R:95, R/summarize.R:209, R/depth.R:312) — name it tf_na_like().
  • ==.tfb <- eval(==.tfd) (R/ops.R:66-73) is a no-op dressed as a copy — eval(fn) returns the same function. Plain `==.tfb` <- `==.tfd`.
  • Trapezoid quadrature weights implemented 4× in package code (R/tfb-mfpc.R:371, R/tfb-fpc.R:49 with a #TODO admitting the duplication, R/tfb-fpc-utils.R:52, R/registration-class.R:246) + a 5th time in tests. One helper.
  • The tfd.* / tfb_spline.* / tfb_fpc.* constructor families each re-implement input canonicalization with divergent behavior — route through the existing mat_2_df/df_2_df funnel.

Performance landmines

  • R/evaluate.R:113-127: list-arg tf_evaluate.tfb calls basis(x[!seen]) (full mgcv Predict.matrix) per curve. 10k curves = 10k design-matrix constructions. Batch on the unique-arg union, index per curve.
  • R/fwise.R:155-157: tf_crosscor recomputes tf_interpolate + tf_fmean ~6× over the same data.
  • R/summarize.R:16: summarize_tf densifies irregular vectors onto the union grid.

Misc

  • R/geom-mv.R contains differential geometry (norm, inner, tangent, arclength), not a ggplot Geom — name collides with ggplot vocabulary that the tidyfun ecosystem uses for actual geoms. Rename geometry-mv.R.
  • R/registration-class.R:217-232 (also covered in the registration summary issue) — but the cli_alert_warning() use at R/split-combine.R:137 is a separate problem: terminal output, not a warning condition; suppressWarnings/tryCatch can't see it; violates the project's own CLAUDE.md "Use cli::cli_abort() or cli::cli_warning() for errors and warnings".
  • R/rng.R:11,32: "Matèrn" — wrong accent; should be "Matérn".
  • R/split-combine.R:77: strict = F in example code (T/F as logicals).
  • 55 lines >100 chars with air.toml present — run the formatter.

Found in the June-2026 ground-up review. Treat as a backlog; cherry-pick into PRs as opportunity allows.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions