...This places an obligation on all creators of software to program in such aHe was referring to prime directive from Star Trek. One of the practice in this direction is to have a proper checks in place for the types we use. We can trust that if we pass for example a wrong type to our function, it will fail gracefully. So a type system of a programming language is quite important in mission critical numerical computations. Since R language is weakly typed language, or dynamically typed similar to Perl, Python or Matlab/Octave, most of R users omit to place type checks in their functions if not rarely. For example take the following function that takes arguments of a matrix, a vector and a function name. It applies the named function to each columns of the matrix listed in the given vector. Assuming named function is returning a single number our function will return a vector of numbers.
way that the computations can be understood and trusted. This obligation
I label the Prime Directive.
myMatrixOperation <- function(A, v, fName) { sliceA <- A[, v]; apply(sliceA, 2, fName); }
myMatrixOperation <- function(A, v, fName) { if(!is.matrix(A)) { stop("A is not a matrix"); } if(!is.vector(v)) { stop("v is not a vector"); } if(!is.funcion(fName)) { stop("fName is not a function"); } sliceA <- A[, v]; apply(sliceA, 2, fName); }
setClass("mySlice", representation(A="matrix", v="vector", fName="function")) myS <- new("mySlice",, A=matrix(rnorm(9),3,3),v=c(1,2), fName=mean) str(myS) Formal class 'mySlice' [package ".GlobalEnv"] with 3 slots ..@ A : num [1:3, 1:3] 0.356 -0.34 -0.642 -0.466 2.915 ... ..@ v : num [1:2] 1 2 ..@ fName:function (x, ...)
Now if we re-write the function that uses our S4 class with type checking only to passing object once.
is.mySlice <- function(obj) { l <- FALSE if(class(obj)[1] == "mySlice") { l <- TRUE } l } myMatrixOperation <- function(mySliceObject) { if(!is.mySlice(mySliceObject)) { stop("argument is not class of mySlice") } sliceA <- mySliceObject@A[, mySliceObject@v]; apply(sliceA, 2, mySliceObject@fName); }