The Big R-Book. Philippe J. S. De Brouwer

The Big R-Book - Philippe J. S. De Brouwer


Скачать книгу
thinks now it is a data.frame ## [1] name balance ## <0 rows> (or 0-length row.names) paul_account[[2]] # the data is still correct ## [1] 200 class(paul_account) <- “account” print(paul_account) # back to normal: the class is just an attribute ## [1] “account holder: Paul” ## [1] “balance : 200”

      6.2.2 Creating Generic Methods

       UseMethod()

      UseMethod() takes two arguments: the name of the generic function, and the argument to use for the method dispatch. If you omit the second argument it will dispatch on the first argument to the function. There is no need to pass any of the arguments of the generic to UseMethod(), R will take care of that for you.

      # add_balance # Dispatcher function to handle the action of adding a given amount # to the balance of an account object. # Arguments: # x -- account -- the account object # amount -- numeric -- the amount to add to the balance add_balance <- function(x, amount) UseMethod(“add_balance”)

      This construct will do nothing else than trying to dispatch the real action to other functions. However, since we did not program them yet, there is nothing to dispatch to. To add those methods, it is sufficient to create a function that has the right naming convention.

      # add_balance.account # Object specific function for an account for the dispatcher # function add_balance() # Arguments: # x -- account -- the account object # amount -- numeric -- the amount to add to the balance add_balance.account <- function(x, amount) { x[[2]] <- x[[2]] + amount; # Note that much more testing and logic can go here # It is not so easy to pass a pointer to a function so we # return the new balance: x[[2]]} my_curr_acc <- add_balance(my_curr_acc, 225) print(my_curr_acc) ## [1] 325

      Leaving the code up to this level is not really safe. It is wise to foresee a default action in case the function add_balance() is called with an object of another class.

      # add_balance.default # The default action for the dispatcher function add_balance # Arguments: # x -- account -- the account object # amount -- numeric -- the amount to add to the balance add_balance.default <- function(x, amount) { stop(“Object provided not of type account.”) }

      6.2.3 Method Dispatch

      The way this works in R is by calling UseMethod() in the dispatching function. This creates a vector of function names, like

       UseMethod()

      paste0(“generic”, “.”, c(class(x), “default”))

      and dispatches to the most specific handling function available. The default class is the last in the list and is the last resort: if R does not find a class specific method it will call the default action.

      Beneath you can see this in action:

      # probe # Dispatcher function # Arguments: # x -- account object # Returns # confirmation of object type probe <- function(x) UseMethod(“probe”) # probe.account # action for account object for dispatcher function probe() # Arguments: # x -- account object # Returns # confirmation of object “account” probe.account <- function(x) “This is a bank account” # probe.default # action if an incorrect object type is provided to probe() # Arguments: # x -- account object # Returns # error message probe.default <- function(x) “Sorry. Unknown class” probe (structure(list(), class = “account”)) ## [1] “This is a bank account” # No method for class ‘customer’, fallback to ‘account’ probe(structure(list(), class = c(“customer”, “account”))) ## [1] “This is a bank account” # No method for class ‘customer’, so falls back to default probe(structure(list(), class = “customer”)) ## [1] “Sorry. Unknown class” probe(df) # fallback to default for data.frame ## [1] “Sorry. Unknown class” probe.account(df) # force R to use the account method ## [1] “This is a bank account” my_curr_acc <- account(“Philippe”, 150) # real account probe(my_curr_acc) ## [1] “This is a bank account”

      image Note – Avoid direct calls

      image Hint – Speed gain

      6.2.4 Group Generic Functions

      The four “group generics” and the functions they include are:

      1 Group Math: Members of this group dispatch on x. Most members accept only one argument, except log, round and signif that accept one or two arguments, while trunc accepts one or more. Members of this group are:abs, sign, sqrt, floor, ceiling, trunc, round, signifexp, log, expm1, log1p, cos, sin, tan, cospi, sinpi, tanpi, acos, asin, atan cosh, sinh, tanh, acosh, asinh, atanhlgamma, gamma, digamma, trigammacumsum, cumprod, cummax, cummin

      2 Group Ops: This group contains both binary and unary operators ( +, - and !): when a unary operator is encountered, the Ops method is called with one argument and e2 is missing. The classes of both arguments are considered in dispatching any member of this group. For each argument, its vector of classes is examined to see if there is a matching specific (preferred) or Ops method. If a method is found for just one argument or the same method is found for both, it is used. If different methods are found, there is a warning about incompatible methods: in that case or if no method


Скачать книгу