Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to add functions in an existing environment

Tags:

r

Is it possible to use env() as a substitute for namespaces, and how do you check if an environment exists already before adding functions to it?

This is related to this question, and Brendan's suggestion How to organize large R programs? I understand Dirk's point in that question, however for development it is sometimes impractical to put functions in packages.

EDIT: The idea is to mimic namespaces across files, and hence to be able to load different files independently. If a file has been previously loaded then the environment doesn't need to be created, just added to.

Thanks for ideas

EDIT: So presumably this code below would be the equivalent of namespaces in other languages:-

 # how to use environment as namespaces

# file 1

# equivalent of 'namespace e' if (!(exists("e") && is.environment(e))) {   e <- new.env(parent=baseenv()) }

e$f1 <- function(x) {1}


# file 2
# equivalent of 'namespace e' if (!(exists("e") && is.environment(e))) {   e <- new.env(parent=baseenv()) }

e$f2 <- function(x) {2}
like image 653
user4 Avatar asked Jan 25 '12 12:01

user4


People also ask

What is the environment function in R?

The environment is a virtual space that is triggered when an interpreter of a programming language is launched. Simply, the environment is a collection of all the objects, variables, and functions.

How do you define a function in R?

In R, a function is an object so the R interpreter is able to pass control to the function, along with arguments that may be necessary for the function to accomplish the actions. The function in turn performs its task and returns control to the interpreter as well as any result which may be stored in other objects.

How do you create an environment in R?

To create an environment manually, use new. env() . You can list the bindings in the environment's frame with ls() and see its parent with parent. env() .

When you want to make an object that was defined in your function accessible to the global environment what function would you use?

If you really want to assign to the global environment you can use the assign function and tell it explicitly that you want to assign globally.


2 Answers

Yes you can for the most part. Each function has an environment and that's where it looks for other functions and global variables. By using your own environment you have full control over that.

Typically functions are also assigned to an environment (by assigning them to a name), and typically those two environments are the same - but not always. In a package, the namespace environment is used for both, but then the (different) package environment on the search path also has the same (exported) functions defined. So there the environments are different.

# this will ensure only stats and packages later on the search list are searched for
# functions from your code (similar to import in a package)
e <- new.env(parent=as.environment("package:stats"))

# simple alternative if you want access to everything
# e <- new.env(parent=globalenv())

# Make all functions in "myfile.R" have e as environment
source("myfile.R", local=e)

# Or change an existing function to have a new environment:
e$myfunc <- function(x) sin(x)
environment(e$myfunc) <- e

# Alternative one-liner:
e$myfunc <- local(function(x) sin(x), e)

# Attach it if you want to be able to call them as usual.
# Note that this creates a new environment "myenv".
attach(e, name="myenv")

# remove all temp objects
rm(list=ls())

# and try your new function:
myfunc(1:3)

# Detach when it's time to clean up or reattach an updated version...
detach("myfile")

In the example above, e corresponds to a namespace and the attached "myenv" corresponds to a package environment (like "package:stats" on the search path).

like image 87
Tommy Avatar answered Nov 15 '22 18:11

Tommy


Namespaces are environments, so you can use exactly the same mechanism. Since R uses lexical scoping the parent of the environment defines what the function will see (i.e. how free variables are bound). And exactly like namespace you can attach environments and look them up.

So to create a new "manual namespace" you can use something like

e <- new.env(parent=baseenv())
# use local(), sys.source(), source() or e$foo <- assignment to populate it, e.g.
local({
  f <- function() { ... }
  #...
}, e)
attach(e, name = "mySuperNamespace")

Now it is loaded and attached just like a namespace - so you can use f just like it was in a namespace. Namespaces use one more parent environment to resolve imports - you can do that too if you care. If you need to check for your cool environment, just check the search path, e.g "mySuperNamespace" %in% search(). If you need the actual environment, use as.environment("mySuperNamespace")

like image 37
Simon Urbanek Avatar answered Nov 15 '22 17:11

Simon Urbanek