'could not find function' error even though fun is in NAMESPACE and has an .Rd file

Hi there,
I've just built my first R package, so I'm very new to understanding package development. I haven't been able to find the answer to this question on this forum or others, but please bear with me if the answer is really obvious and I'm just not googling correctly.

I created a small package and put it up on Github. I documented in using devtools and roxygen2. Then I installed the package using devtools::install_github() and loaded it with library(); then I attempted to use functions from the package. Most of the functions worked, but for just one of the functions, I'm getting the error "could not find function".

I know that this "could not find function" error typically happens when the package in question isn't properly installed and loaded. I double checked that the package was both installed and loaded (and even opened up a new R session and re-installed and re-loaded it to make sure). devtools::document() ran with no errors or warnings, and a .Rd file was successfully created for the function in question. The line export(functionname) is present in the NAMESPACE file.

The package is on Github here. The function that I can't get to work is preprocessData(). The other functions seem to work fine.

My guess:
preprocessData() is different from the other functions in the package in that it calls other package functions: it's a wrapper for fixNames() and removeGeo(). I wonder if the error is happening because it's invalid to have functions call each other within a package? This SO post seems to have a similar error, but based on the responses there I think I should be in the clear: the functions are in the same namespace, the documentation is updated, etc. This post also seems to say that it's fine to have functions in the same package call each other.

So I'm not sure what I'm missing. Can anyone help figure out why I'm having this problem? I'd like to write some other wrapper functions, but I'm hesitant to start if it's going to turn out that this isn't a valid thing to do.

Thank you!

I tried installing and no problem with finding the function:

library(ygdpAddSurvey)

df <- data.frame(`Response ID` = c("Response ID", LETTERS[1:3]),
                 x = 1:4,check.names = FALSE)
preprocessData(df)
#> Error in worcesterRemove(df1): could not find function "worcesterRemove"

Created on 2020-12-18 by the reprex package (v0.3.0)

So you should probably try to reinstall your package from the latest version, possibly with force = TRUE.

(then I get this separate problem of worcesterRemove() not found. Also I had some trouble understanding the format of the Response ID column, I had to read the source of fixNames() to understand that it was not supposed to be the column name, but rather the first row)

Thanks! I understand what's happening with the worcesterRemove function, so I should be able to fix that. Just today I started having another problem installing this package and I think you're right, force = T is what I need to do here.

I'm definitely aware that there are some problems with the formats and that this is confusing if you're coming into it blind! This is not going to be a package for general use, just a way of storing functions for a really really specific application. But I appreciate you pointing it out, and I may work on the documentation there a bit.

1 Like

Right, I'm just telling you about the format because sometimes an external point of view can help uncover difficulties that are not obvious to the person working on it : )

Makes sense, thank you.

I'm actually still stuck on this 'can't find function' thing, and I think it's a problem with how I'm installing/loading the package, rather than a problem with my package itself. I fixed the problems you pointed out (and made some other changes to the package code). I committed those changes and pushed them to the package repo on Github. But I can't get the changes to show up in my working R session unless I close the session and open a new one.

I think I need to figure out how to uninstall and/or unload the package without restarting the R session. I googled that, and found resources that told me to use detach("package:ygdpAddSurvey", unload = TRUE) to remove the package, and then try re-installing it (with force = TRUE) and re-loading it with library(). But I tried that, and no dice--the updated function code still doesn't show up unless I close my R session, open a new session, and do install_github() within that new R session.

Do you know if there are additional commands I can use to actually fully uninstall the package from within my R session so that I can reinstall it and use the newly-updated code?

I think this explains why you had no trouble finding the function I posted about above--you were installing the package for the first time, while I had it already installed.

Thanks!

uninstall.packages() from installr looks like it should work, but it looks like installr isn't compatible with my version of R (4.0.3), nor did it work with 3.6.3 before I updated R just now.

I also tried remove.packages("ygdpAddSurvey") and then re-installed the package from github via devtools::install_github(), but when I did that, I got this message:

Error in fetch(key) : 
  lazy-load database '/Library/Frameworks/R.framework/Versions/4.0/Resources/library/ygdpAddSurvey/help/ygdpAddSurvey.rdb' is corrupt

I had previously been following the devtools workflow, so load_all() does simulate that quite well (just reload the whole package in its latest version).

But why do you want to update the package without restarting the session? Isn't that a good thing to avoid conflicts between previous and new versions of functions?

I guess so. I think my workflow is all wrong--I've been developing the package in one R project, pushing it to github, and then installing it in a separate R project where the scripts that actually use the package are contained (i.e. not in the package directory itself). Seems like that's really not how you're supposed to do it. But I think I'm stuck with this for now, so I'll just keep restarting the session, since as you point out, that's a pretty good thing anyway.

Thanks for your input :slight_smile:

Or I think you can just create a new, separate, directory, and clone the latest version of the package from Github. Then you can use the devtools, including install(), that makes it available in your other project with library(). But of course that will create some amount of headache at first, compared to your workflow that already works.

I had some similar frustrations creating my first package or two. RStudio can & will run R's initialization function under circumstances that I don't fully understand nor have researched. To help collect data, I added some message calls to .First(). My rprofile.site repo has additional documentation.

Two debugging techniques that may be useful:

  • Invoke the function using the double colon notation - package-name::function-name.
  • Use pryr to see if the memory address of the function has changed. Details in Advanced R.

W/regard to your comment

-I've been developing the package in one R project, pushing it to github, and then installing it in a separate R project where the scripts that actually use the package are contained (i.e. not in the package directory itself).

This is more or less how I develop my packages on my computer. What I don't understand is what you mean by 'installing it in a separate R project'. My process is:

  1. Push working package to GitHub.
  2. devtools::install_github()
  3. In your R script, add library("my_package")

Installing a package just writes the files in the directory pointed to by R_LIBS_USER. Run Sys.getenv("R_LIBS_USER") to see where your current R environment is looking for packages.

2 Likes

Thanks, @dgabbe, these are helpful tips! I had tried using the double colon, and you're right that it sounds like our workflows are similar.

When I said "installing it in a separate R project," I just meant that I had been running devtools::install_github() in a different R project (.Rproj) than the one contained in the package directory itself. I wasn't doing that because I thought I had to--it was just an artifact of the fact that I wanted to use the package functions in some code that already had its own .Rproj. You're right that installing a package writes the files to a directory, so it shouldn't matter which project I'm installing from.

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.

If you have a query related to it or one of the replies, start a new topic and refer back with a link.