1

I have a package that generates some functions when you call an initialize function. I create these functions in the parent.frame of initialize(), which I guess is the global environment. I want to emulate the normal package behavior that allows you to directly call a function from a package after loading it, but without having to see those functions when you list your workspace contents using ls(). For example, doing

library(ggplot2)
ls()

doesn't return geom_line, geom_point, etc., but you don't have to use :: to call those functions. They are exposed to the user but do not live in the global environment.

Is there a clever way for me to do the same thing for functions generated by the call to initialize, e.g. by defining environments or namespaces in zzz.r and the onLoad or onAttach hooks? I thought of trying to set the function environments to the package namespace, but it seems that you cannot modify the package namespace after it is loaded.

EDIT the package I'm working on is here: https://github.com/mkoohafkan/arcpyr. The arcpy.initialize function connects to Python using PythonInR, imports the arcpy package, and then creates interfaces for a list of functions. I'll try to create a simplified dummy package later today.

mikeck
  • 3,534
  • 1
  • 26
  • 39
  • 1
    Sure @Hack-R, I edited my question with a link. I'll try to create a simpler version later today. – mikeck Oct 08 '16 at 21:40
  • 1
    Function names that start with a `.` will not show up with `ls()`. Not exactly "clever" and not very safe if other packages use the same trick. – Eric Oct 08 '16 at 22:00
  • 1
    Why do you need to create these functions dynamically? Why not have them exist in your package's namespace, but have them throw an error if Python isn't initialized yet? – shadowtalker Oct 08 '16 at 22:03
  • 1
    perhaps http://stackoverflow.com/questions/3094232/add-objects-to-package-namespace – hrbrmstr Oct 08 '16 at 22:55
  • @ssdecontrol, I'm using the `PythonInR` package to access a python module, and the package automatically creates R function interfaces for Python functions I import. There are a lot of functions (and the list changes slightly depending on the version of ArcGIS installed) so it would be extremely tedious to manually create the interfaces in the package namespace. I'm open to suggestions though. – mikeck Oct 09 '16 at 18:06
  • Thanks @hrbrmstr---that thread showed me that I can' modify the list of exported functions after loading the package, which is why I'm focusing this question on trying to exclude the functions from `ls()`. But if you know of a way to push the functions to the export list, that would be the ideal solution. – mikeck Oct 09 '16 at 18:15
  • 1
    @mikeck another solution would be to create and export an _environment_, or perhaps even an R6 class, which you can modify dynamically to your heart's content. E.g. instead of just calling an initializing function, you have your users create an instance of this environment, `arcpy <- arcpy::ArcPy()` which then holds all the functions you create, e.g. `arcpy$some_python_function()`. – shadowtalker Oct 09 '16 at 20:26
  • Thanks @ssdecontrol, that's a great suggestion---probably the best compromise for what I'm trying to do. – mikeck Oct 11 '16 at 21:23

1 Answers1

0

So I eventually found a solution that uses both environments (thanks @ssdecontrol!) and attach.

f = new.env()                   # create the environment f
assign("foo", "bar", pos = f)   # create the variable foo inside f
ls()                            # lists f
ls(f)                           # lists foo
attach(f)                       # attach f to the current environment
foo                             # foo can now be accessed directly
## bar
ls()                            # but still only shows f
rm(f)                           # can even remove f
foo                             # and foo is still accessible
## bar

Of course, there are some risks to using attach.

I redid the arcpyr package to use environments instead, but you can get the old behavior back by doing

arcpy = arcpy_env()
attach(arcpy)
mikeck
  • 3,534
  • 1
  • 26
  • 39
  • You could use `with(f,{...})`. That being said, the behavior you're describing is what happens when a namespace is **attached**, so with `attach` you do produce the desired effect – moodymudskipper Jul 13 '18 at 21:59