1

I was looking at some code earlier today (https://www.r-bloggers.com/building-your-own-blockchain-in-r/) where someone was defining S3 functions in a way that I'd never seen before and liked the visual style, but have never seen it anywhere else in R code and wanted to figure out why.

They defined a number of S3 classes that looked like

my_class <- function(){
  # set some attributes
  inst <- list(foo = "bar")

  # define a function
  inst$change_foo <- function(what) {inst$foo <- what}

  # get S3 class right
  class(inst) <- "my_class"
  inst <- list2env(inst)
  inst
}

Basically, it strikes me that this person was trying to make R's generic-function S3 OO system look like the more standard message-passing OO system (a la Python, Java, etc) where methods belong to classes.

My sense is that this is probably bad practice in R, since

baz <- my_class()
baz$change_foo("baz")

doesn't really do what you think it does. My, admittedly thin, understanding is that in other object oriented languages, baz$change_foo is actually bound to that instance of my_class, so it will always edit baz.

In R, that binding doesn't actually happen, and so the inst in the my_class definition could find a different inst than baz if it happens to be in the environment.

It's only that list2env call that keeps things tidy here, and that could get messed up in a more complicated example.

I do like the way this code visually encapsulates functions for my_class, so I'm curious if I'm onto something here, or if I'm getting all worked up over nothing. Denizens of Stack Overflow, what say you? Is this good style or bad?

Alex Gold
  • 335
  • 1
  • 9

1 Answers1

0

I am assuming that the question is to comment on the approach and what exists along those lines.

First note that this can be simplified by using the runtime environment within the myClass function itself rather than creating a new environment:

myClass <- function() {
   foo <- "bar"
   change_foo <- function(what) foo <<- what
   environment()
}

# test
baz <- myClass()
baz$change_foo("baz")
baz$foo
## [1] "baz"

The idea of fashioning OO systems from R's base functionality has been around for years. For example this demo that comes with R has been there since the early days:

demo("scoping")

There are also a number of OO systems in R or R packages that use environments. For example, look at Reference Classes in R itself (from within R ?ReferenceClasses) and the CRAN packages proto, R.oo and R6. Reference Classes were introduced in R 2.12 which is after both S3 and S4. proto and R.oo were first released in 2005 and R6 in 2014. ggplot2 was originally written in proto and the author of R.oo has written a number of packages using it.The gWidgets2 package is a rewrite of the gWidgets package using S3 and Reference Classes.

G. Grothendieck
  • 254,981
  • 17
  • 203
  • 341