## the executable code to complete the generics corresponding to primitives, ## and to define the group generics for these functions. ## uses the primitive list and the function .addBasicGeneric ## defined (earlier) in BasicFunsList.R .makeBasicFuns<- function(where) { env <- new.env(hash=TRUE, parent=as.environment(where)) funs <- get(".BasicFunsList", envir=where) ## First, set up the existing functions in the list as valid generics. curNames <- names(funs) for(i in seq(along=funs)) { val <- funs[[i]] if(is.function(val)) funs <- .addBasicGeneric(funs, curNames[[i]], val, "", env) } ## the Math group. members <- c("log", "sqrt", "log10", "cumprod", "abs", "acos", "acosh", "asin", "asinh", "atan", "atanh", "ceiling", "cos", "cosh", "cumsum", "exp", "floor", "gamma", "lgamma", "sin", "sinh", "tan", "tanh") for(f in members) funs <- .addBasicGeneric(funs, f, function(x) standardGeneric(""), "Math", env) setGroupGeneric(where=where,"Math", function(x)NULL, knownMembers = members, package = "base") ## The Math2 group. In spite of the documented behaviror, there ## is an S3 method for trun with a SECOND argument. Until we get ## a better solution, we have to put trunc in the Math2 group. funs <- .addBasicGeneric(funs, "trunc", function(x, digits = 0) standardGeneric(""), "Math2", env) funs <- .addBasicGeneric(funs, "round", function(x, digits = 0) standardGeneric(""), "Math2", env) funs <- .addBasicGeneric(funs, "signif", function(x, digits = 6) standardGeneric(""), "Math2", env) setGroupGeneric(where = where, "Math2", function(x, digits) NULL, knownMembers = c("round", "signif"), package = "methods") ## The Arith group members <- c("+", "-", "*", "^", "%%", "%/%", "/") for(f in members) funs <- .addBasicGeneric(funs, f, function(e1, e2) standardGeneric(""), "Arith", env) setGroupGeneric(where = where, "Arith", function(e1, e2)NULL, group = "Ops", knownMembers = members, package = "base") ## the Compare group members <- c("==", ">", "<", "!=", "<=", ">=") for(f in members) funs <- .addBasicGeneric(funs, f, function(e1, e2) standardGeneric(""), "Compare", env) setGroupGeneric(where = where, "Compare", function(e1, e2)NULL, group = "Ops", knownMembers = members, package = "methods") ## R does not currently do the Logic group (! & |) ## A strange group, since the argument lists are different. But ## perhaps we'll add it sometime. ## the Ops group generic setGroupGeneric(where = where,"Ops", function(e1, e2)NULL, knownMembers = c("Arith", "Compare"), package = "base") ## The Summary group ## These are a bit problematic, since they essentially have "..." ## as their only data-related formal argument. The treatment ## since S3 has been to define the generic with a special first ## argument, to allow method dispatch. But the method had better ## invoke the generic recursively or perform some other special ## computations, in order to avoid unintended anomalies, such as ## !identical(max(x,y), max(y,x)) members <- c("max", "min", "range", "prod", "sum", "any", "all") for(f in members) funs <- .addBasicGeneric(funs, f, function (x, ..., na.rm = FALSE) standardGeneric(""), "Summary", env) setGroupGeneric(where = where, "Summary", function(x, ..., na.rm = FALSE) NULL, knownMembers = members, package = "base") ## The Complex group ## R adds this group to the previous S language function groups, ## for all the operations defined on complex numbers. For ## applications wanting to define a new class that extends the ## concept of complex numbers, a function group is likely to be ## useful since all these functions may operate in a similar ## manner (by analogy, e.g., with the Math group). members <- c("Arg", "Conj", "Im", "Mod", "Re") for(f in members) funs <- .addBasicGeneric(funs, f, function(z) standardGeneric(""), "Complex", env) setGroupGeneric(where=where,"Complex", function(z)NULL, knownMembers = members, package = "base") assign(".BasicFunsList", funs, envir=where) assign(".BasicFunsEnv", env, envir=where) rm(.addBasicGeneric, envir=where) } .BasicFunsMethods <- list() .InitSubsetMethods <- function(where) { ## create some methods for the functions in .BasicFunsList. ## The strategy on initialization is to create the methods list ## objects by setMethod calls, and then move them to the ## .BasicFunsMethods list, from which they will be retrieved when ## the generic is installed; see getGeneric. ## The mlist objects can not be left in the methods library itself ## after initialization, since the basic functions are not "turned ## on" as generics until some other package or user defines ## methods for them. ## This facility is not currently instantiated, though there are ## some desirable changes to the "[" and related functions, to ## untangle the current messing with "drop" and multiple ## subscripts, in the vector case. }