Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What are these square brackets for S3 classes?

Tags:

r

r-s3

I obtained this from an open source repo on git. This shows the writing of generic and methods for S3 classes. But I do not understand the notations or conventions that the functions are being assigned to. The following are my questions:

  • The use backticks `` to define the function name. Usually we wouldn't use backticks or even double quotes to assign variables/functions but I see this happening a lot of times. Is this a naming convention?
  • Why is the . included before the blob name? Usually wouldn't it just be called blob and a method would be method.blob?
  • Why are there [ brackets there? Especially, [<- and [[<-. Are we performing some sort of double asigning?

Hopefully someone will be able to shed some light on what is ha

#' @export
 `[.blob`  <- function(x, i, ...) {
  new_blob(NextMethod())
}

#' @export
`[<-.blob` <- function(x, i, ..., value) {
  if (!is_raw_list(value)) {
    stop("RHS must be list of raw vectors", call. = FALSE)
  }

  NextMethod()
}

#' @export
 `[[<-.blob` <- function(x, i, ..., value) {
  if (!is.raw(value) && !is.null(value)) {
    stop("RHS must be raw vector or NULL", call. = FALSE)
  }

  if (is.null(value)) {
    x[i] <- list(NULL)
    x
  } else {
    NextMethod()
  }
}
like image 401
Justin Thong Avatar asked Mar 07 '23 11:03

Justin Thong


1 Answers

Summary

If you're creating a new object in R for which you want 'different' subset and assignment behaviour, you should create the associated methods for these operations.

  • The . IS working in the way you're expecting - method dispatch

  • [.blob is overriding the S3 [ subset operator

  • [<-.blob is overriding the S3 [<- operator (i.e. vector-subset assignment)

  • [[<-.blob is overriding the S3 [[<- operator (i.e. list-subset assignment)

  • Special symbols (e.g., backticks, brackets, percent-sign, variables with spaces in the name) cannot be "assigned to" by default. To do so, if you surround it in backticks, it can work. As an example, a variable named A B cannot be assigned with A B <- 1, whereas `A B` <- 1 works (credit @r2evans)

Examples

subset

Taking [.blob as an example, this allows you to create your own subset operation for your blob object.

## Create your own blob object (class)
blob <- 1:5
attr(blob, "class") <- "blob"

## create a subset operator, which in this example just calls the next method in the s3 dispatch chain 
`[.blob` <- function(x, i, j, ...) NextMethod()

As we're not doing anything special in our own subset method, this works like normal R vectors

blob[3]
# [1] 3

However, we can make the subset operation do whatever we want, for example always return the 1st element of the vector

## define the function to always subset the first element
`[.blob` <- function(x, i, j, ...) { i = 1; NextMethod() }

Now your blob object will only ever return the 1st element.

blob[1]
# [1] 1
blob[2]
# [1] 1
blob[3]
# [1] 1

Assignment

Similarly for one of the assignment operators, if you overload [<- with

`[<-.blob` <- function(x, i, j, ...) { i = 5; NextMethod() }

This will always assign the 5th element of your blob object with the new value

blob[1] <- 100
blob
# [1]   1   2   3   4 100
# attr(,"class")
# [1] "blob"

Back ticks

The back-ticks are used so we can assign functions/variables to special symbols.

For example, try to assign a vector to the [ symbol

[ <- 1:5
# Error: unexpected '[' in "["

Whereas surrounding it with ticks lets it pass (although this example is not recommended)

`[` <- 1:5
`[`
# [1] 1 2 3 4 5
like image 147
SymbolixAU Avatar answered Mar 15 '23 15:03

SymbolixAU