Active Bindings in R

Aug 14, 2018 · 326 words · 2 minutes read R

Yihui Xie and Colin Fray wrote some great posts (1, 2) about active bindings and the makeActiveBinding function in R.

Binding occurs anytime you use assignment, i.e. x <- "hello" binds x to the string “hello”. An active binding is one where the assignee (e.g. x) returns the value from a function. You can create active bindings using the makeActiveBinding function.

From the documentation:

makeActiveBinding installs fun in environment env so that getting the value of sym calls fun with no arguments, and assigning to sym calls fun with one argument, the value to be assigned.

Here’s an example of creating an active binding on a variable called one_or_two:

makeActiveBinding(
  sym = "one_or_two",
  fun = function(x){
    sample(1:2, size = 1)
  },
  env = .GlobalEnv
)
one_or_two
## [1] 1
one_or_two
## [1] 1
typeof(one_or_two)
## [1] "integer"

See how one_or_two looks like a variable but returns different values like a function? one_or_two is a variable (it’s type is integer) but the value depends on a function call. The binding between the assignee and assignment is still “active” and can change. That’s active binding.

This looks like a neat trick but also a good opportunity to introduce confusion. Programmers usually won’t expect the value of a variable to change unless they see a new value being assigned.

Why would you want to use active bindings? Why have a variable that acts like a function but simply not use a function? We can turn back to the documentation:

… This allows the implementation of things like C variables linked to R variables and variables linked to databases, and is used to implement setRefClass. It may also be useful for making thread-safe versions of some system globals.

So active bindings are a way to link R variables to values in other places (outside of R). This is, for example, how the reticulate package provides a means of interacting with a Python session. You can find other examples on Github.