## ----include = FALSE---------------------------------------------------------- knitr::opts_chunk$set( collapse = TRUE, comment = "#>" ) ## ----setup-------------------------------------------------------------------- library(S7) ## ----performance, cache = FALSE----------------------------------------------- Text <- new_class("Text", parent = class_character) Number <- new_class("Number", parent = class_double) x <- Text("hi") y <- Number(1) foo_S7 <- new_generic("foo_S7", "x") method(foo_S7, Text) <- function(x, ...) paste0(x, "-foo") foo_S3 <- function(x, ...) { UseMethod("foo_S3") } foo_S3.Text <- function(x, ...) { paste0(x, "-foo") } library(methods) setOldClass(c("Number", "numeric", "S7_object")) setOldClass(c("Text", "character", "S7_object")) setGeneric("foo_S4", function(x, ...) standardGeneric("foo_S4")) setMethod("foo_S4", c("Text"), function(x, ...) paste0(x, "-foo")) # Measure performance of single dispatch bench::mark(foo_S7(x), foo_S3(x), foo_S4(x)) bar_S7 <- new_generic("bar_S7", c("x", "y")) method(bar_S7, list(Text, Number)) <- function(x, y, ...) paste0(x, "-", y, "-bar") setGeneric("bar_S4", function(x, y, ...) standardGeneric("bar_S4")) setMethod("bar_S4", c("Text", "Number"), function(x, y, ...) paste0(x, "-", y, "-bar")) # Measure performance of double dispatch bench::mark(bar_S7(x, y), bar_S4(x, y)) ## ----performance-2, message = FALSE, R.options = list(width = 120), cache = TRUE-------------------------------------- library(S7) gen_character <- function (n, min = 5, max = 25, values = c(letters, LETTERS, 0:9)) { lengths <- sample(min:max, replace = TRUE, size = n) values <- sample(values, sum(lengths), replace = TRUE) starts <- c(1, cumsum(lengths)[-n] + 1) ends <- cumsum(lengths) mapply(function(start, end) paste0(values[start:end], collapse=""), starts, ends) } bench::press( num_classes = c(3, 5, 10, 50, 100), class_nchar = c(15, 100), { # Construct a class hierarchy with that number of classes Text <- new_class("Text", parent = class_character) parent <- Text classes <- gen_character(num_classes, min = class_nchar, max = class_nchar) env <- new.env() for (x in classes) { assign(x, new_class(x, parent = parent), env) parent <- get(x, env) } # Get the last defined class cls <- parent # Construct an object of that class x <- do.call(cls, list("hi")) # Define a generic and a method for the last class (best case scenario) foo_S7 <- new_generic("foo_S7", "x") method(foo_S7, cls) <- function(x, ...) paste0(x, "-foo") # Define a generic and a method for the first class (worst case scenario) foo2_S7 <- new_generic("foo2_S7", "x") method(foo2_S7, S7_object) <- function(x, ...) paste0(x, "-foo") bench::mark( best = foo_S7(x), worst = foo2_S7(x) ) } ) ## ----performance-3, message = FALSE, R.options = list(width = 120), cache = TRUE-------------------------------------- bench::press( num_classes = c(3, 5, 10, 50, 100), class_nchar = c(15, 100), { # Construct a class hierarchy with that number of classes Text <- new_class("Text", parent = class_character) parent <- Text classes <- gen_character(num_classes, min = class_nchar, max = class_nchar) env <- new.env() for (x in classes) { assign(x, new_class(x, parent = parent), env) parent <- get(x, env) } # Get the last defined class cls <- parent # Construct an object of that class x <- do.call(cls, list("hi")) y <- do.call(cls, list("ho")) # Define a generic and a method for the last class (best case scenario) foo_S7 <- new_generic("foo_S7", c("x", "y")) method(foo_S7, list(cls, cls)) <- function(x, y, ...) paste0(x, y, "-foo") # Define a generic and a method for the first class (worst case scenario) foo2_S7 <- new_generic("foo2_S7", c("x", "y")) method(foo2_S7, list(S7_object, S7_object)) <- function(x, y, ...) paste0(x, y, "-foo") bench::mark( best = foo_S7(x, y), worst = foo2_S7(x, y) ) } )