# Why does expressing one function require(ctest) t.test # return only function (x, ...) UseMethod("t.test") <environment: namespace:ctest> # but expressing another function shapiro.test # returns more complete code? function (x) { DNAME <- deparse(substitute(x)) x <- sort(x[complete.cases(x)]) n <- length(x) if (n < 3 || n > 5000) stop("sample size must be between 3 and 5000") rng <- x[n] - x[1] if (rng == 0) stop("all `x[]' are identical") if (rng < 1e-10) x <- x/rng n2 <- n%/%2 sw <- .C("swilk", init = FALSE, as.single(x), n, n1 = as.integer(n), as.integer(n2), a = single(n2), w = double(1), pw = double(1), ifault = integer(1), PACKAGE = "ctest") if (sw$ifault && sw$ifault != 7) stop(paste("ifault=", sw$ifault, ". This should not happen")) RVAL <- list(statistic = c(W = sw$w), p.value = sw$pw, method = "Shapiro-Wilk normality test", data.name = DNAME) class(RVAL) <- "htest" return(RVAL) } <environment: namespace:ctest> -- Richard E. Remington III Statistician KERN Statistical Services, Inc. PO Box 1046 Boise, ID 83701 Tel: 208.426.0113 KernStat.com
On Tue, 9 Dec 2003, Remington, Richard wrote:> # Why does expressing one function > > require(ctest) > t.test > > # return only > > function (x, ...) > UseMethod("t.test") > <environment: namespace:ctest> > > # but expressing another function > > shapiro.test > > # returns more complete code?[...] False hypothesis: both are the complete code. You are not understanding (S3-style) generic functions: see any good book on R/S. (`An Introduction to R' is based on notes that predate them, but they are covered in more detail in the draft R Language manual. `The reader is referred to the official references for a complete discussion of this mechanism.' which I think means Chambers & Hastie, 1992,) -- Brian D. Ripley, ripley at stats.ox.ac.uk Professor of Applied Statistics, http://www.stats.ox.ac.uk/~ripley/ University of Oxford, Tel: +44 1865 272861 (self) 1 South Parks Road, +44 1865 272866 (PA) Oxford OX1 3TG, UK Fax: +44 1865 272595
Remington, Richard wrote:> # Why does expressing one function > > require(ctest) > t.test > > # return only > > function (x, ...) > UseMethod("t.test") > <environment: namespace:ctest> > > # but expressing another function > > shapiro.test > > # returns more complete code? > > function (x) > { > DNAME <- deparse(substitute(x)) > x <- sort(x[complete.cases(x)]) > n <- length(x) > if (n < 3 || n > 5000) > stop("sample size must be between 3 and 5000")... Short answer: Unless you're programming your own functions, you don't need to worry about that. Long answer: Because the first is generic - it looks at what kind of data you're testing (two vectors, a formula, whatever, ...) and calls the appropriate sub-function. shapiro.test does not; it just takes one data format, and stops in its tracks if that's not what you've provided. The ideas behind this are documented in "Writing R Extensions" (R-exts.pdf) which is supplied with binary R distributions, and is available from CRAN. See chapter 6, "Generic functions and methods", in the version that accompanies R-1.8.1. Cheers Jason -- Indigo Industrial Controls Ltd. http://www.indigoindustrial.co.nz 64-21-343-545 jasont at indigoindustrial.co.nz
Perhaps what should be added to the previous answers is that you can find out where the real work is done like this: require(ctest) t.test methods(t.test) ctest:::t.test.default ctest:::t.test.formula If the class of the first argument to t.test is formula then t.test.formula gets invoked so that's where the real work is done; otherwise, t.test.default gets invoked so that's where the real work is done. --- Remington, Richard wrote:> # Why does expressing one function > > require(ctest) > t.test > > # return only > > function (x, ...) > UseMethod("t.test") > <environment: namespace:ctest> > > # but expressing another function > > shapiro.test > > # returns more complete code? > > function (x) > { > DNAME <- deparse(substitute(x)) > x <- sort(x[complete.cases(x)]) > n <- length(x) > if (n < 3 || n > 5000) > stop("sample size must be between 3 and 5000")