Skip to content

Fix namespace lookup failures in superbData without attaching package#10

Open
achetverikov wants to merge 2 commits into
dcousin3:masterfrom
achetverikov:fix-ddply-function-lookup
Open

Fix namespace lookup failures in superbData without attaching package#10
achetverikov wants to merge 2 commits into
dcousin3:masterfrom
achetverikov:fix-ddply-function-lookup

Conversation

@achetverikov
Copy link
Copy Markdown

Summary

This PR fixes a namespace lookup failure in superbData() / superbPlot() when users pass namespaced strings like statistic = "superb::mean" and errorbar = "superb::CI" without attaching superb to the search path.

It also removes global-environment side effects in superbPlot() by eliminating dynamic wrapper creation (superbSTATISTIC / superbERRORBAR in .GlobalEnv).

Problem

1) HyunhFeldtEpsilon lookup failure (within-subject CM/LM path)

In superbPlot(), diagnostics used:

  • plyr::ddply(..., .fun = "HyunhFeldtEpsilon", ...)
  • plyr::ddply(..., .fun = "WinerCompoundSymmetryTest", ...)
  • plyr::ddply(..., .fun = "MauchlySphericityTest", ...)

With string .fun, plyr resolves via match.fun() and caller/search-path lookup.
When superb is not attached, this can fail with:

object 'HyunhFeldtEpsilon' of mode 'function' was not found

2) Global environment mutation

superbPlot() created temporary wrappers in .GlobalEnv via eval(parse(...), envir = globalenv()):

  • superbSTATISTIC
  • init.superbSTATISTIC
  • superbERRORBAR

This introduces side effects and can interfere with package usage patterns.

Changes

Commit 1: Use function objects in ddply sphericity diagnostics

In R/superbPlot.R, replaced string .fun with function objects:

  • "HyunhFeldtEpsilon" -> HyunhFeldtEpsilon
  • "WinerCompoundSymmetryTest" -> WinerCompoundSymmetryTest
  • "MauchlySphericityTest" -> MauchlySphericityTest

This removes fragile search-path function lookup in the CM/LM diagnostics block.

Commit 2: Remove globalenv wrappers for statistic and errorbar

In R/superbPlot.R:

  • Removed eval(parse(...), envir = globalenv()) wrapper generation.
  • Resolved statistic/errorbar/init functions as local function objects.
  • Replaced string-based do.call("...") calls with direct function-object calls.
  • Kept existing user API (statistic/errorbar as strings, including "namespace::name").
  • Preserved existing feedback messages and behavior.

Repro (before)

data(sleep, package = "datasets")
sleep_wide <- reshape(sleep, direction = "wide", idvar = "ID", timevar = "group")

superb::superbData(
  sleep_wide,
  WSFactors   = "group(2)",
  variables   = c("extra.1", "extra.2"),
  adjustments = list(purpose = "single", decorrelation = "CM"),
  statistic   = "superb::mean",
  errorbar    = "superb::CI"
)

Could fail with:

object 'HyunhFeldtEpsilon' of mode 'function' was not found

Validation

  • Full test suite run: PASS 291, FAIL 0, WARN 0, SKIP 0.
  • Side-by-side output comparison (CRAN superb vs patched) across between/within/mixed examples, with and without gamma:
    • Outputs are identical (max_abs_diff = 0) for all previously working cases.
    • Only behavior change: previously failing non-attached within-subject case now works.
  • Confirmed no global env artifacts after calls:
    • exists("superbSTATISTIC", .GlobalEnv, inherits = FALSE) -> FALSE
    • exists("superbERRORBAR", .GlobalEnv, inherits = FALSE) -> FALSE

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant