I am working on a package and currently it has a lot of functions. Inorder to load them every time I open up RStudio, I use this line of code from devtools:
library(devtools)
suppressMessages(load_all("~/Codes/package1/"))
It works fine, but the problem is whenever I change a function that has been used in another function, R doesn't recognize the changes.
For Example if I have:
func1 <- function() {
print("version1")
}
func2 <- function() {
func1()
}
And then change func1 to print("Vesion2"), rerun it and then run func2, it would still print version1 for me.
Anyone knows whats the problem and how can I solve it?
The devtools load_all function simulates loading a package. All functions from a package are stored in a package namespace. Functions remember what namespace they come from via their environment().
Any code you run in the console runs in the global environment. So when you run
func1 <- function() {print("version2")}
you are creating a new function called func1 in your global environment but the func1 from the package namespace is still there. You've created a "shadow" function that masks the original function.
When you got to run func2 which is still in the package namespace, it sees a call to a function named func1. When it goes to look for this function, it looks first in it's own namespace due to R's lexical scoping rules. It finds the original funct1 and not the one you created in the global environment so it runs that.
Packages generally aren't meant to have their functions swapped or altered after they are loaded. You would save to save the source and call load_all to reload that folder as a package with the new changes. If you aren't really trying to simulate a package, importing functions with source() will not create a new namespace and would therefore be easier to edit after import.
Related
I have a function that is part of my own package. When called from namespace:package_name, the function behaves slightly different than when it is called from R_GlobalEnv. To find out why I want to debug the function.
To make debugging the function as easy as possible, I want to write the changes I made to the function to the namespace:package_name environment, so I can immediately test it, but I cannot figure out how to do this.
If I type namespace:package_name, it gives the environment at the bottom as follows:
<bytecode: 0x00000236403c9da0>
<environment: namespace:package_name>
But if I try environment(fun) <- namespace:package_name, it says:
Error: object 'namespace' not found.
How do I set the environment of my function to the package environment?
EDIT:
Surprisingly fixInNamespace does not leave the namespace intact.
I created a package with some functions which are helpful at my company. Recently, I restructered the package such that there are helper functions which need not to be accessible for everyone, but are called internally from other (exported) functions of the package. These helper functions are not exported to the namespace (no #' #export in the respective .R files).
Now, when I call one of the "major" (exported) functions, I get the error message (no real function names):
Error in major_function() : could not find function "helper_function"
Im fairly new in building packages, but from what I understood so far (from https://cran.r-project.org/web/packages/roxygen2/vignettes/namespace.html), it should neither be necessary to export the helper functions, nor to add #' importFrom my_package helper_function to the .R file of the major function.
When I tried this, it actually produced errors when checking the package. I also tried to call the helper functions with my_package:::helper_function, but this lead to the note that it should almost never be necessary to call functions from the same package like this.
Maybe useful information:
The error occurs only when I call a major_function_1 which internally calls major_function_2 which calls a helper_function.
I think there is more to your problem than what you state. As long as all your functions are defined in the same namespace (this also means that all your functions need to live in .R files in the same folder), the calling function should find the helper-functions accordingly.
I suspect you have your helper functions nested in some way, and that is causing the problem.
I recommend to recheck your namespace structure, or post a simplistic outline of your package here.
Another reason that could come to mind, is that you do not export your 'mayor_function2' in your NAMESPACE-file in your package root (maybe you have not recompiled the Roxygen documentation generating this file), and additionally have a local shadow of the the calling function 'mayor_function1'. Try to check this and rerun from a clean compile.
my R package has a function (my_func) that uses function(bar) from another package (foo) which only available on Unix. So I write my code this way, following the suggested packages in Writing R extension:
my_func = function(){
....
if (requireNamespace("foo", quietly = TRUE)) {
foo::bar(..) # also tried bar(...)
} else {
# do something else without `bar`
}
...
}
However, I keep getting such warning message when I run R CMD check:
'loadNamespace' or 'requireNamespace' call not declared from: foo
Is there any way to use platform specific packages without gives such warnings? I tried to include foo in the Description file and the warning disappeared, but then the package cannot be installed on windows because foo is not available for the win.
I think you misread that comment, though it is easy to do because the logic is not clear and incontrovertible.
In that first paragraph that talked about calling packages using require(package) they said it was OK for a test environment or vignette but not from inside a finished function to use library(package) or require(package).
This is considered bad form, because the packages you call inside a function will usurp the order of access your user has set up in her work environment when loading packages.
The method you use above:
package::function()
is the approved of way to use a function within a function without altering the current environment.
But in order to use that function you must still have that package installed on your current machine or in your current working environment (such as a virtualenv or ipython or jupytr..and yes R will work in all those environments).
You cannot run a function that R cannot see from the working environment...so you must have it installed, but not necessarily loaded, to call it.
I have an R package with bunch of functions (all are exported). One of the function calls another function internally while running. But when I run this function via namespace without loading the entire package, it throws an error: 'could not find function ..'
For e.g:
foo and bar are two functions. foo calls bar internally. But when I call foo via namespace i.e, mypackage::foo() it throws an error could not find function "bar". If I load the library first and run via namespace it runs properly.
#doesnot work
mypackage::foo()
could not find function "bar"
#works
library(mypackage)
mypackage::foo()
I have exported both function and both are present in NAMESPACE file.
The problem with using the :: or ::: fuc[nctions is that only the function code is pulled into the workspace. So none of ancillary or supporting functions in that mypackage are pulled into the "interpreter space", i.e. the objects that the interpreter can see. So you option 2 "works" and your option 1 fails. For what seem to me to be obvious reasons.
When I am hacking a function that I know is derived from a loaded a namespace, I generally finish the hacking process with:
environment(hacked_fun) <- environment(orig_fun)
But that's not an option when you pull code from disk with the "mult-colon-functions". This is also a major reason why experienced R programmmers do their development in packages.The coding discipline of making a package also supports defining package dependencies.
I am sourcing util functions in production into an environment to encapsulate (and group) the helper functions:
Helper file:
# File: Helper.R
hello <- function() {
print("Hello world")
}
Client:
helper <- new.env()
source("Helper.R", local=helper)
helper$hello() # call the helper function
How can I migrate my sourced "Helper.R" into a library without breaking the calls of the sourced functions?
What I want is something like
helper <- new.env()
library(Helper, local=helper)
helper$hello() # call the helper function (loaded from the library now)
Is there a way to do this?
You can use the box::use() function in the ‘box’ package.
Then the following attaches a package locally:
box::use(pkg[...])
Alternatively, and potentially closer to what you actually want to do, you could use the following simpler code:
box::use(pkg)
Now the package is not attached at all, and its exported objects can be accessed via pkg$obj. This is somewhat similar to base R’s loadNamespace function, but does considerably more behind the scenes.
Finally, consider not putting your helper code into a package at all, but rather distributing it as a module. This is after all what the ‘box’ package was designed for: instead of creating a package, just distribute your helper.r code file (or folder) and then use it as follows:
box::use(./helper)
See the package website and vignette for a detailed description.
Adding to the list of suggestions you can also consider to use the modules package on CRAN (note I am the author). When you have your Helper.R file with:
hello <- function() {
print("Hello world")
}
you can use
helper <- modules::use("Helper.R")
helper$hello()
to encapsulate your helper functions in their own environment. The package also provides some functions to manipulate the local namespace of a module (imports/exports).
I have found another package called import (similar to "modules") that allows importing packages into an environment:
https://github.com/smbache/import
This package is also on CRAN:
install.packages("import")
It allows importing selected, all exported ("public") or all (even not exported) functions of a package.
Example:
import::from(dplyr, arrange, .into = "datatools")
The import::from function is a convenient wrapper around getExportedValue.
Another way could be:
# getNamespace returns the environment representing the name space name. The namespace is loaded if necessary.
# Internal function to support reflection on namespace objects!
env <- getNamespace("data.table")
cars <- env$as.data.table(mtcars)
This examples makes all objects of the package data.table available via the environment variable env.
Note: It uses an internal R function (I have no idea how big the risk of changes of this internal function really is).