Rev 84054 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed
R Under development (unstable) (2023-03-26 r84067) -- "Unsuffered Consequences"Copyright (C) 2023 The R Foundation for Statistical ComputingPlatform: x86_64-pc-linux-gnu (64-bit)R is free software and comes with ABSOLUTELY NO WARRANTY.You are welcome to redistribute it under certain conditions.Type 'license()' or 'licence()' for distribution details.R is a collaborative project with many contributors.Type 'contributors()' for more information and'citation()' on how to cite R or R packages in publications.Type 'demo()' for some demos, 'help()' for on-line help, or'help.start()' for an HTML browser interface to help.Type 'q()' to quit R.> #### Testing UseMethod() and even more NextMethod()> #### --------------------> #### i.e., S3 methods *only*. For S4, see reg-S4.R> ## ~~~~~~~~>> ###-- Group methods>> ## previous versions used print() and hit an auto-printing bug.>> ### Arithmetic "Ops" :> ">.bar" <- function(...) {cat("using >.bar\n"); FALSE}> ">.foo" <- function(...) {cat("using >.foo\n"); TRUE}> Ops.foo <- function(...) {+ cat("using Ops.foo\n")+ NextMethod()+ }> Ops.bar <- function(...) {+ cat("using Ops.bar\n")+ TRUE+ }>> x <- 2:4 ; class(x) <- c("foo", "bar")> y <- 4:2 ; class(y) <- c("bar", "foo")>> ## The next 4 give a warning each about incompatible methods:> x > y[1] FALSE FALSE TRUEWarning message:Incompatible methods (">.foo", ">.bar") for ">"> y < x # should be the same (warning msg not, however)[1] FALSE FALSE TRUEWarning message:Incompatible methods ("Ops.bar", "Ops.foo") for "<"> x == y[1] FALSE TRUE FALSEWarning message:Incompatible methods ("Ops.foo", "Ops.bar") for "=="> x <= y[1] TRUE TRUE FALSEWarning message:Incompatible methods ("Ops.foo", "Ops.bar") for "<=">> x > 3 ##[1] ">.foo"using >.foo[1] TRUE>> rm(list=">.foo")> x > 3 #-> "Ops.foo" and ">.bar"using Ops.foousing >.bar[1] FALSE>>>> ### ------------ was ./mode-methods.R till R ver. 1.0.x ---------------->> ###-- Using Method Dispatch on "mode" etc :> ## Tests S3 dispatch with the class attr forced to be data.class> ## Not very relevant when S4 methods are around, but kept for historical interest> abc <- function(x, ...) {+ cat("abc: Before dispatching; x has class `", class(x), "':", sep="")+ str(x)+ UseMethod("abc", x) ## UseMethod("abc") (as in S) fails+ }>> abc.default <- function(x, ...) sys.call()>> "abc.(" <- function(x)+ cat("'(' method of abc:", deparse(sys.call(sys.parent())),"\n")> abc.expression <- function(x)+ cat("'expression' method of abc:", deparse(sys.call(sys.parent())),"\n")>> abc(1)abc: Before dispatching; x has class `numeric': num 1abc.default(1)> e0 <- expression((x))> e1 <- expression(sin(x))> abc(e0)abc: Before dispatching; x has class `expression': expression((x))'expression' method of abc: abc.expression(e0)> abc(e1)abc: Before dispatching; x has class `expression': expression(sin(x))'expression' method of abc: abc.expression(e1)> abc(e0[[1]])abc: Before dispatching; x has class `(': language, mode "(": (x)'(' method of abc: `abc.(`(e0[[1]])> abc(e1[[1]])abc: Before dispatching; x has class `call': language sin(x)abc.default(e1[[1]])>>> ## Some tests for `nameOfClass()`, called from inherits()> ClassX <- structure(list(), name = "ClassX",+ class = c("S3pp_class", "S3pp_object"))>> classx_instance <- structure(list(), class = c("ClassX", "S3pp_object"))>> nameOfClass.S3pp_class <- function(x) attr(x, "name", TRUE)> nameOfClass.foo <- function(x) "bar">> stopifnot(exprs = {+ inherits(classx_instance, "ClassX")+ inherits(classx_instance, ClassX)+ ## ignore class on a character object+ isTRUE(inherits(1, structure("numeric", class = "foo")))+ ## make sure class is nor evaluated in calling nameOfClass+ isFALSE(inherits(1, structure(quote(stop("should not be evaluated")),+ class = "foo")))+ })>>> ## Some tests for `@` dispatching> ## make sure that> ## - `@` evals the first args only once,> ## - doesn't dispatch for S4> ## - works on `.Data` even for nonS4 objects>> x <- structure(list(), class = "foo", prop1 = 'prop1val')> registerS3method("@", "foo",+ function(x, name) {+ stopifnot(typeof(name) == "character", length(name) == 1L)+ cat(sprintf("called `@.foo`(x = %s, name = '%s')\n",+ deparse1(substitute(x), "\n"), name))+ attr(x, name, TRUE)+ }+ )> x@prop1called `@.foo`(x = x, name = 'prop1')[1] "prop1val">> abc <- x> abc@prop1called `@.foo`(x = abc, name = 'prop1')[1] "prop1val">> {+ cat("new x\n")+ structure(list(), class = "foo", prop1 = 'prop1val')+ }@prop1new xcalled `@.foo`(x = {cat("new x\n")structure(list(), class = "foo", prop1 = "prop1val")}, name = 'prop1')[1] "prop1val">> makeActiveBinding("ax", function(x) {+ cat("evaluating ax\n")+ get("x", envir = parent.frame())+ }, environment())>> ax@prop1evaluating axcalled `@.foo`(x = ax, name = 'prop1')[1] "prop1val">> stopifnot(exprs = {+ identical( x@prop1, "prop1val")+ identical(ax@prop1, "prop1val")++ identical(letters@.Data, letters)+ })called `@.foo`(x = x, name = 'prop1')evaluating axcalled `@.foo`(x = ax, name = 'prop1')>> try(letters@foo) # errorError in letters@foo :no applicable method for `@` applied to an object of class "character">> # doesn't dispatch for S4> setClass("Person",+ slots = c(+ name = "character",+ age = "numeric"+ )+ )>> `@.Person` <- function(x, name) {+ stop("called @.Person()\n")+ }>> p <- new("Person", name = "Who", age = -1)> stopifnot(p@name == "Who")>>> ## Some tests for `chooseOpsMethod()`, called from C DispatchGroup() when> ## 2 methods are found> foo_obj <- structure(1, class = "foo")> bar_obj <- structure(1, class = "bar")>> `+.foo` <- function(e1, e2) "foo"> `+.bar` <- function(e1, e2) "bar">> invisible(foo_obj + bar_obj) # Warning: Incompatible methodsWarning message:Incompatible methods ("+.foo", "+.bar") for "+">> chooseOpsMethod.bar <- function(x, y, mx, my, cl, reverse) TRUE>> stopifnot(exprs = {+ identical(foo_obj + bar_obj, "bar")+ identical(bar_obj + foo_obj, "bar")+ })>