10

Is there a way to automatically import all hidden functions from a package, ie functions accessible only with package:::fun ?

Indeed I have brought some modifications to a given function which uses quite a lot of internal functions and I want to avoid retyping package::: everywhere.

I looked at loadNamespace base function but it does not attach the non exported ones.

ClementWalter
  • 4,814
  • 1
  • 32
  • 54
  • 1
    Can you give some more background? Is, e.g., creating a branch of the package and building it with your modifications an option? – Roland Jun 15 '16 at 10:39

2 Answers2

10

Ok I finally found sort of a hack using this related post and eval:

# get all the function names of the given package "mypack"
r <- unclass(lsf.str(envir = asNamespace("mypack"), all = T))

# filter weird names
r <- r[-grep("\\[", r)]
r <- r[-grep("<-", r)]

# create functions in the Global Env. with the same name
for(name in r) eval(parse(text=paste0(name, '<-mypack:::', name)))

I would have thought there were some prebuilt function to do this anyway.

ClementWalter
  • 4,814
  • 1
  • 32
  • 54
  • thanks for pointing this out. this is because of some wired names (don't know what these functions are), you should add some filtering, see my edited answer – ClementWalter Jun 15 '16 at 11:49
  • Thank you very much, it works, it's very useful for some occasion for external packages used. Little addendum: to not launch one or both of `r <- r[-grep(, r)]` if they found nothing (`integer(0)`) else `r` return `character(empty)`, or replace by `r<-if (any(grep("\\[", r) )) r[-grep("\\[", r)] else r` and `r<-if (any(grep("<-", r) )) r[-grep("<-", r)] else r` – phili_b Mar 03 '23 at 13:26
  • Sorry to be harsh, but this is an insanely convoluted, poorly working hack for something that can be done in a single line of code: `list2env(as.list(asNamespace(pkgname), all.names = TRUE), envir = environment())`. However, there is virtually *no* use-case where indiscriminately dumping all package names into the current environment is a good idea. – Konrad Rudolph Jul 11 '23 at 09:45
2

I don’t think dumping non-exported names from a package into the current environment is ever a good idea:1 there’s a reason why these functions are not exported, and at the point where you find yourself accessing them in bulk you should stop and rethink your approach.

Given your specific use-case (edit a function from a package that needs to use non-exported names internally), a better solution would be to assign the package namespace as the function’s environment:

the_edited_function = function (…) { … }
environment(the_edited_function) = asNamespace('the_package')

… of course it goes without saying that this is also a horrible hack and should rarely be necessary.


1 It can be done with a single expression:

list2env(as.list(asNamespace('the_package'), all.names = TRUE), envir = environment())

… but, really, don’t do this.

Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214