The hardware and bandwidth for this mirror is donated by dogado GmbH, the Webhosting and Full Service-Cloud Provider. Check out our Wordpress Tutorial.
If you wish to report a bug, or if you are interested in having us mirror your free-software or open-source project, please feel free to contact us at mirror[@]dogado.de.
Active bindings in R are much like properties in other languages:
They look like a variable, but querying or setting the value triggers a
function call. They can be created in R via makeActiveBinding()
,
but with this API the function used to compute or change the value of a
binding cannot take additional arguments. The bindr
package
faciliates the creation of active bindings that are linked to a function
that receives the binding name, and an arbitrary number of additional
arguments.
You can install bindr
from GitHub with:
# install.packages("devtools")
::install_github("krlmlr/bindr") devtools
For illustration, the append_random()
function is used.
This function appends a separator (a dash by default) and a random
letter to its input, and talks about it, too.
set.seed(20161510)
<- function(x, sep = "-") {
append_random message("Evaluating append_random(sep = ", deparse(sep), ")")
paste(x, sample(letters, 1), sep = sep)
}
append_random("a")
#> Evaluating append_random(sep = "-")
#> [1] "a-h"
append_random("X", sep = "+")
#> Evaluating append_random(sep = "+")
#> [1] "X+k"
In this example, we create an environment that contains bindings for
all lowercase letters, which are evaluated with
append_random()
. As a result, a dash and a random letter
are appended to the name of the binding:
library(bindr)
<- create_env(letters, append_random)
env ls(env)
#> [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q" "r" "s"
#> [20] "t" "u" "v" "w" "x" "y" "z"
$a
env#> Evaluating append_random(sep = "-")
#> [1] "a-s"
$a
env#> Evaluating append_random(sep = "-")
#> [1] "a-h"
$a
env#> Evaluating append_random(sep = "-")
#> [1] "a-c"
$c
env#> Evaluating append_random(sep = "-")
#> [1] "c-o"
$Z
env#> NULL
Bindings can also be added to existing environments:
populate_env(env, LETTERS, append_random, "+")
#> Evaluating append_random(sep = "-")
#> Evaluating append_random(sep = "-")
#> Evaluating append_random(sep = "-")
#> Evaluating append_random(sep = "-")
#> Evaluating append_random(sep = "-")
#> Evaluating append_random(sep = "-")
#> Evaluating append_random(sep = "-")
#> Evaluating append_random(sep = "-")
#> Evaluating append_random(sep = "-")
#> Evaluating append_random(sep = "-")
#> Evaluating append_random(sep = "-")
#> Evaluating append_random(sep = "-")
#> Evaluating append_random(sep = "-")
#> Evaluating append_random(sep = "-")
#> Evaluating append_random(sep = "-")
#> Evaluating append_random(sep = "-")
#> Evaluating append_random(sep = "-")
#> Evaluating append_random(sep = "-")
#> Evaluating append_random(sep = "-")
#> Evaluating append_random(sep = "-")
#> Evaluating append_random(sep = "-")
#> Evaluating append_random(sep = "-")
#> Evaluating append_random(sep = "-")
#> Evaluating append_random(sep = "-")
#> Evaluating append_random(sep = "-")
#> Evaluating append_random(sep = "-")
$a
env#> Evaluating append_random(sep = "-")
#> [1] "a-q"
$Z
env#> Evaluating append_random(sep = "+")
#> [1] "Z+c"
Both named and unnamed arguments are supported:
create_env("binding", paste, "value", sep = "-")$binding
#> [1] "binding-value"
A parent environment can be specified for creation:
<- create_env("a", identity, .enclos = env)
env2 $a
env2#> a
$b
env2#> NULL
get("b", env2)
#> Evaluating append_random(sep = "-")
#> [1] "b-t"
The bindings by default have access to the calling environment:
<- function(names) {
create_local_env <- function(...) paste(..., sep = "-")
paste_with_dash <- function(name, append) paste_with_dash(name, append)
binder create_env(names, binder, append = "appending")
}
<- create_local_env("a")
env3 $a
env3#> [1] "a-appending"
All bindings are read-only:
$a <- NA
env3#> Error: Binding is read-only.
$a <- NULL
env3#> Error: Binding is read-only.
Existing variables or bindings are not overwritten:
<- as.environment(list(a = 5))
env4 populate_env(env4, list(quote(b)), identity)
ls(env4)
#> [1] "a" "b"
populate_env(env4, letters, identity)
#> Error in populate_env(env4, letters, identity): Not creating bindings for existing variables: b, a
Active bindings must be R functions. To interface with C++ code, one
must bind against an exported Rcpp function, possibly with
rng = false
if performance matters. The bindrcpp
package uses bindr
to provide an easy-to-use C++ interface
for parametrized active bindings, and is the recommended way to
interface with C++ code. In the remainder of this section, an
alternative using an exported C++ function is shown.
The following C++ module exports a function
change_case(to_upper = FALSE)
, which is bound against in R
code later.
#include <Rcpp.h>
#include <algorithm>
#include <string>
using namespace Rcpp;
// [[Rcpp::export(rng = FALSE)]]
(Symbol name, bool to_upper = false) {
SEXP change_casestd::string name_string = name.c_str();
std::transform(name_string.begin(), name_string.end(),
.begin(), to_upper ? ::toupper : ::tolower);
name_stringreturn CharacterVector(name_string);
}
Binding from R:
<- create_env(list(as.name("__ToLower__")), change_case)
env populate_env(env, list(as.name("__tOuPPER__")), change_case, TRUE)
ls(env)
#> [1] "__ToLower__" "__tOuPPER__"
$`__ToLower__`
env#> [1] "__tolower__"
get("__tOuPPER__", env)
#> [1] "__TOUPPER__"
These binaries (installable software) and packages are in development.
They may not be fully stable and should be used with caution. We make no claims about them.
Health stats visible at Monitor.