Skip to content
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

do.call()`: ! 'what' must be a function or character string -- can't build pkg on top of NMF package #183

Open
elisagdelope opened this issue May 15, 2024 · 0 comments

Comments

@elisagdelope
Copy link

Description:
I've encountered an issue with the NMF package that complicates building packages that use NMF functions. Specifically, the problem arises when attempting to use NMF functions within my package without explicitly loading the NMF library. Here are the details:

Environment Setup:

  • NMF is listed as an Imports in the DESCRIPTION file.
  • NMF functions are imported in the NAMESPACE and functions.R files (I tried both using @import and @importFrom the corresponding functions' roxygen2 tags).
  • NMF functions are called with the NMF:: prefix (e.g., NMF::nmf()).

Observed Behavior:
When calling my package function that uses NMF functions internally, an error occurs unless library(NMF) is explicitly called beforehand. This behavior is specific to the NMF package and does not occur with other packages.

Error Traceback:

Error in `do.call()`:
! 'what' must be a function or character string
Backtrace:
  1. funOmics::summarize_pathway_level(X, kegg_sets, type = "nmf")
  2. funOmics:::aggby_dimred(ifunmat, type)
  4. NMF::nmf(X, rank = 1)
  6. NMF::nmf(x, rank, NULL, ...)
  7. NMF (local) .local(x, rank, method, ...)
  9. NMF::nmf(x, rank, method, seed = seed, model = model, ...)
 11. NMF::nmf(x, rank, method = strategy, ...)
 12. NMF (local) .local(x, rank, method, ...)
 13. base::do.call(...)

I've identified an issue in NMF package that makes it very hard to build on top of it. I'm building a package where one of the functions uses the NMF package. The NMF package is an import in the DESCRIPTION file, and it is imported both in the NAMESPACE file and in the functions.R file, where the functions are located (in roxygen2 format @import, @importFrom). I have also tried to call the functions as NMF::nmf() and NMF::coef() instead of just nmf() and coef(), however the error persists.

The error (see below) only gets removed if I explicitly load the library itself, this is, if I have library(NMF) before calling the package function that, internally, uses one of its functions. I have explored a range of possible solutions to avoid forcing users to load this library explicitly when the package is used, but i have not been successful. Notably, this issue only happens with this library, not with any other.

Reproducible Test:
Without attaching NMF, I ran:

> do.call(NMF::nmf, list(matrix(), rank = 1))

This works and returns an error specific to the function:

Error: NMF::nmf - Input matrix x contains at least one null or NA-filled row.
In addition: Warning message:
In min(x, na.rm = TRUE) : no non-missing arguments to min; returning Inf

On the other hand if I just specify nmf directly:

> do.call(nmf, list(matrix(), rank = 1))

Yields:

Error in h(simpleError(msg, call)) :
  error in evaluating the argument 'what' in selecting a method for function 'do.call': object 'nmf' not found

Not quite the same error but pointing to the problem -- do.call() looks on the search path (packages that are attached) not in packages that are merely loaded. So, somewhere in the nmf code there is a do.call() that assumes the object is on the search path.

Analysis:
The issue seems to be related to a do.call() usage within the NMF code that assumes the function is on the search path, i.e., the package must be attached via library(NMF).

Suggested Solution:
Please modify the NMF package to ensure functions can be reliably called using the NMF:: prefix, without requiring the package to be attached. This will improve compatibility with packages that import NMF functions, avoiding the need to depend on NMF explicitly.

This is an important issue for the NMF maintainer to fix; otherwise I don't think there's an easy way for to work around when building on top of NMF functions other than Depending on NMF, which is frankly far from ideal (NMF should be an import, just like any other package whose functions are used).

Fixing this issue would greatly enhance the usability of NMF in broader package development and align with best practices for R package dependencies.

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

No branches or pull requests

1 participant