3

I simply need a R function like:

> la. <- function (envir = globalenv()) {ls(all = T, envir = envir) }`

with an active binding so I do need to type brackets

> makeActiveBinding('la', la., globalenv())

So that

> la
[1]  "la"  "la."

I now want to implement function la() and it bind la inside a package So that when I load the package, la is ready available.

How can I bind function la.() to the symbol la within the package environment?

What value shall I pass to the envir argument of function makeActiveBinding()

Thanks for any help

Andrea
  • 593
  • 2
  • 8
  • 1
    The given solution don't pass the CMD check for me because the active binding is evaluated and fails. – moodymudskipper Aug 26 '20 at 00:45
  • An additional issue is documenting active bindings, I didn't manage to do it without triggering annoying warnings when loading the workspace. – moodymudskipper Aug 26 '20 at 00:48
  • @Moody_Mudskipper Check [my new answer](https://stackoverflow.com/a/70722230/1968), it passes `R CMD check`, generates proper documentation, and shouldn’t trigger any warnings. – Konrad Rudolph Jan 15 '22 at 14:18

3 Answers3

2

Calling namespaceExport manually causes R CMD check to complain. Instead, the export declaration should be put into the NAMESPACE file.

Or, when using ‘roxygen2’, add the @export tag in front of a dummy NULL object to make it generate the appropriate documentation and NAMESPACE export declaration:

#' List objects
#' @usage la
#' @name la
#' @export
NULL

makeActiveBinding(
    'la',
    function () ls(envir = globalenv(), all.names = TRUE),
    environment()
)

Where

  • @usage causes ‘roxygen’ to generate a “Usage” section, which would otherwise be missing
  • @name tells ‘roxygen2’ the object name, to be used for the export declaration and for the name of the help page (this can be overridden with @rdname if necessary)
  • @export marks the name as exported, as usual.

Note also that the use of .onLoad is not required to declare active bindings: they can be defined directly at namespace/file level.

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

This is probably something to do in the .onLoad function, something like this in your package:

NAMESPACE <- environment()

la. <- function(){ 
  ls(all = T, envir = globalenv())
}

.onLoad <- function(libname, pkgname) {
  makeActiveBinding("la", la., NAMESPACE)
}
Romain Francois
  • 17,432
  • 3
  • 51
  • 77
0

I think this should work:

Lets write two functions inside a package:

# function one
ll_ <- function(){
  ls(envir = globalenv(), all.names = TRUE)
}

# function two
l_ <- function(){
  ls(envir = globalenv(), all.names = FALSE)
}

then write your onLoad() function

# Runs when package is loaeded
.onLoad <- function(libname, pkgname) {
  ns <-  asNamespace(pkgname)
  makeActiveBinding("ll", ll_,  env = ns) 
  makeActiveBinding("l", l_,  env = ns) 
  namespaceExport(ns, c('ll','l'))
}

When loading your packages, commands l and ll. run functions l() and ll()

Finally, I am sure that by embedding all function in a list and playing with functionals, the definition of onLoad() may become much lighter

Thanks Romain for your suggestion

Andrea
  • 593
  • 2
  • 8