Hiding Personal Functions in R

hiding personal functions in R

Combine attach and sys.source to source into an environment and attach that environment. Here I have two functions in file my_fun.R:

foo <- function(x) {
mean(x)
}

bar <- function(x) {
sd(x)
}

Before I load these functions, they are obviously not found:

> foo(1:10)
Error: could not find function "foo"
> bar(1:10)
Error: could not find function "bar"

Create an environment and source the file into it:

> myEnv <- new.env()
> sys.source("my_fun.R", envir = myEnv)

Still not visible as we haven't attached anything

> foo(1:10)
Error: could not find function "foo"
> bar(1:10)
Error: could not find function "bar"

and when we do so, they are visible, and because we have attached a copy of the environment to the search path the functions survive being rm()-ed:

> attach(myEnv)
> foo(1:10)
[1] 5.5
> bar(1:10)
[1] 3.027650
> rm(list = ls())
> foo(1:10)
[1] 5.5

I still think you would be better off with your own personal package, but the above might suffice in the meantime. Just remember the copy on the search path is just that, a copy. If the functions are fairly stable and you're not editing them then the above might be useful but it is probably more hassle than it is worth if you are developing the functions and modifying them.

A second option is to just name them all .foo rather than foo as ls() will not return objects named like that unless argument all = TRUE is set:

> .foo <- function(x) mean(x)
> ls()
character(0)
> ls(all = TRUE)
[1] ".foo" ".Random.seed"

R: Source personal scripts keeping some functions hidden

Use:

get("g",env=environment(f))
## function ()
## print("hello")
## <environment: 0x0000000018780c30>

ls(parent.env(environment(f)))
## [1] "g"

Credit goes to Alexander Griffith for the solution.

Hiding a result of a function in R

I would just use an S3 class. Basically, just tag the object z with a particular class

myfunction <- function(){     
#Inside the function I created four results A, B, C, and D.
A = 10;B = 20;C = 30; D = 40
z = list(MacKinnon=A, regression=B, proof=C, res=D)
class(z) = "my_fun" # Tagging here
return(z)
}

Create an S3 print function for my_fun

print.my_fun = function(x, ...) print(x[1:3])

Then

R> x = myfunction()
R> x
$MacKinnon
[1] 10

$regression
[1] 20

$proof
[1] 30

But

R> x$res
[1] 40

gives you want you want.


A couple of comments/pointers.

  • Typically when you assign the class, you would use something like

    class(z) = c("my_fun", class(z))

    however, since we just created z in the line above, this isn't needed.

  • Currently the print method strips away any additional classes (in the example, there is only one class, so it's not a problem). If we wanted to maintain multiple class, we would use

    print.my_fun = function(x, ...) {
    x = structure(x[1:3], class = class(x))
    NextMethod("print")
    }

    The first line of the function subsets x, but maintains all other classes. The second line, then passes x to the next print.class_name function.

Easy way to list my data but not my functions in R? (Hide functions from ls()?)

Put the functions in a package-structured folder (ie in a subfolder called R) and use package:devtools. The only thing you need do is load_all("myfuncs") when you edit your R code. Everything is reloaded into R, doesn't mess up your ls() listings, and is easy to package and document if you need to take this further. But its not compulsory. Just load_all after editing.

How can I hide the documentation of helper functions?

There's a field in the Rd file you can add called keywords. Most keywords don't do anything except help you search for functions with one notable exception: internal. Marking a function with the internal keyword removes it from the index. According to the roxygen2 vignette:

@keywords keyword1 keyword2 ... to add standardised keywords. Keywords are optional, but if present, must be taken from the predefined list replicated in the keywords vignette. Keywords are not very useful, except for @keywords internal. Using the internal keyword removes all functions in the associated .Rd file from the documentation index and disables some of their automated tests. A common use case is to both export a function (using @export) and marking it as internal. That way, advanced users can access a function that new users would be confused about if they were to see it in the index.

Adding @keywords internal to the roxygen comments will give the desired result.

Cleaning up the workspace hiding objects

Try this to leave out the "f-dots":

fless <- function() { ls(env=.GlobalEnv)[!grepl("^f\\.", ls(env=.GlobalEnv) )]}

The ls() function looks at objects in an environment. If you only used (as I initially did) :

fless <- function() ls()[!grepl("^f\\.", ls())]

You get ... nothing. Adding .GlobalEnv moves the focus for ls() out to the usual workspace. The indexing is pretty straightforward. You are just removing (with the ! operator) anything that starts with "f." and since the "." is a special character in regex expressions, you need to escape it, ... and since the "\" is also a special character, the escape needs to be doubled.

How to hide or disable in-function printed message

You can use capture.output with invisible

> invisible(capture.output(y <- ff(2)))
> y
[1] 4

or sink

> sink("file")
> y <- ff(2)
> sink()
> y
[1] 4


Related Topics



Leave a reply



Submit