Reputation: 13
in regards to this post: How can I call two functions with same name from two source files in R?
The example provided shows two functions with the same name coming from two different sources:
in "aa.R"
hi <- function(){
print("hi, aa")
}
in "bb.R"
hi <- function(){
print("hi, bb")
}
Now what I want to do is call function hi from aa.R by refernecing the source. I know when working with packages i can use:
packagename::functionname()
But when working with source(filename.R) it doens't work. One of the provided answers explains to use two different envoirments, which i would not prefer doing, as i feel like this makes it much more accessible to errors.
Also being said, that it's not very smart to name two functions the same name. While I totally agree, that it would make more sense to use different names for functions actually doing something different, i would still prefer calling functions by reference of source, for readability purpose, as i can instantly see the file i am grabbing the function from, while debugging or coding in general.
One more thing: Whats stopping me from creating a package with the functions i am working with? Is there any reason not to create a package from a source-file contianing functions used in my main script?
Thanks for any advice.
Upvotes: 1
Views: 882
Reputation: 270428
Except for (5) these all use the example in the Note at the end.
1) separate environments source
each file into a separate environment and then qualify the name using the appropriate environment when calling the function. this seems very close to library(aa); aa::aa.R
in spirit.
source("aa.R", local = aa <- new.env())
source("bb.R", local = bb <- new.env())
aa$hi()
## [1] "hi, aa"
bb$hi()
## [1] "hi, bb"
1a) A variation of this is to put only one of the hi's in a separate environment. That might be useful in the case that that one is less used.
source("aa.R", local = aa <- new.env())
source("bb.R")
aa$hi()
## [1] "hi, aa"
hi()
## [1] "hi, bb"
1b) A variation of this is to attach them to the search list.
source("aa.R", local = attach(NULL, name = "aa"))
source("bb.R", local = attach(NULL, name = "bb"))
as.environment("aa")$hi()
## [1] "hi, aa"
as.environment("bb")$hi()
## [1] "hi, bb"
2) box Konrad Rudolph's box package (on CRAN) can be used for this. Again this is not much different than library(aa); aa::aa.R
.
box::use(./aa)
box::use(./bb)
aa$hi()
## [1] "hi, aa"
bb$hi()
## [1] "hi, bb"
3) re-source Another approach is to reread the file each time hi
is called.
source("aa.R")
hi()
## [1] "hi, aa"
source("bb.R")
hi()
## [1] "hi, bb"
source("aa.R")
hi()
## [1] "hi, aa"
4) rename Yet another approach is to rename hi each time it is read. This won't work if hi itself is used within the source file but is ok otherwise. (This could also be combined with one of the above solutions.)
source("aa.R")
aa_hi <- hi
rm(hi)
source("bb.R")
bb_hi <- hi
rm(hi)
aa_hi()
## [1] "hi, aa"
bb_hi()
## [1] "hi, bb"
5) S3 In the case that the two instances of hi work on different input classes they could be made to be methods of the same generic. Change the example to this:
cat('hi <- function(x, ...) UseMethod("hi")
hi.numeric <- function(x) {
print(paste("hi, aa -", x))
}', file = "aa.R")
cat('hi <- function(x, ...) UseMethod("hi")
hi.character <- function(x) {
print(paste("hi, bb -", x))
}', file = "bb.R")
source("aa.R")
source("bb.R")
hi(1)
## [1] "hi, aa - 1"
hi("z")
## [1] "hi, bb - z"
6) modules The modules package (on CRAN) can be used.
library(modules)
aa <- use("aa.R")
bb <- use("bb.R")
aa$hi()
## [1] "hi, aa"
bb$hi()
## [1] "hi, bb"
7) package Another possibility is to convert the script to a package. Run the following to convert aa.R to a package, build, install and run it. Similarly for bb.R .
library(pkgKitten)
library(devtools)
setwd("...directory containing aa.R...")
kitten("aa", author = "me") # create empty package
file.copy("aa.R", "aa/R") # add script to it
setwd("aa")
build()
install()
setwd("..")
aa::hi()
## [1] "hi, aa"
Generate the input in reproducible form.
cat('hi <- function() {
print("hi, aa")
}', file = "aa.R")
cat('hi <- function() {
print("hi, bb")
}', file = "bb.R")
Upvotes: 3
Reputation: 2243
Here is an approach based on environments :
my_Fun <- function(path_To_File)
{
source(path_To_File)
new_Env <- new.env()
new_Env$hi <- hi
return(new_Env)
}
env1 <- my_Fun("aa.R")
env2 <- my_Fun("bb.R")
> evalq(hi(), env1)
[1] "hi, aa"
> evalq(hi(), env2)
[1] "hi, bb"
Upvotes: 0