The R Project SVN R

Rev

Rev 84105 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
8504 maechler 1
 
84105 luke 2
R Under development (unstable) (2023-03-26 r84067) -- "Unsuffered Consequences"
83997 luke 3
Copyright (C) 2023 The R Foundation for Statistical Computing
68809 ripley 4
Platform: x86_64-pc-linux-gnu (64-bit)
8504 maechler 5
 
6
R is free software and comes with ABSOLUTELY NO WARRANTY.
7
You are welcome to redistribute it under certain conditions.
39252 ripley 8
Type 'license()' or 'licence()' for distribution details.
8504 maechler 9
 
10
R is a collaborative project with many contributors.
39252 ripley 11
Type 'contributors()' for more information and
12
'citation()' on how to cite R or R packages in publications.
8504 maechler 13
 
39252 ripley 14
Type 'demo()' for some demos, 'help()' for on-line help, or
15
'help.start()' for an HTML browser interface to help.
16
Type 'q()' to quit R.
8504 maechler 17
 
52904 jmc 18
> #### Testing  UseMethod() and even more NextMethod()
19
> #### -------------------- 
20
> #### i.e.,  S3 methods *only*. For S4, see  reg-S4.R
21
> ##                                          ~~~~~~~~
8504 maechler 22
> 
52904 jmc 23
> ###-- Group methods
8504 maechler 24
> 
52904 jmc 25
> ## previous versions used print() and hit an auto-printing bug.
40086 ripley 26
> 
52904 jmc 27
> ### Arithmetic "Ops" :
28
> ">.bar" <- function(...) {cat("using >.bar\n"); FALSE}
29
> ">.foo" <- function(...) {cat("using >.foo\n"); TRUE}
30
> Ops.foo <- function(...) {
31
+     cat("using Ops.foo\n")
32
+     NextMethod()
8504 maechler 33
+ }
52904 jmc 34
> Ops.bar <- function(...) {
35
+     cat("using Ops.bar\n")
36
+     TRUE
40086 ripley 37
+ }
8504 maechler 38
> 
52904 jmc 39
> x <- 2:4 ; class(x) <- c("foo", "bar")
40
> y <- 4:2 ; class(y) <- c("bar", "foo")
8504 maechler 41
> 
52904 jmc 42
> ## The next 4 give a warning each about incompatible methods:
43
> x > y
44
[1] FALSE FALSE  TRUE
45
Warning message:
46
Incompatible methods (">.foo", ">.bar") for ">" 
47
> y < x # should be the same (warning msg not, however)
48
[1] FALSE FALSE  TRUE
49
Warning message:
50
Incompatible methods ("Ops.bar", "Ops.foo") for "<" 
51
> x == y
52
[1] FALSE  TRUE FALSE
53
Warning message:
54
Incompatible methods ("Ops.foo", "Ops.bar") for "==" 
55
> x <= y
56
[1]  TRUE  TRUE FALSE
57
Warning message:
58
Incompatible methods ("Ops.foo", "Ops.bar") for "<=" 
8504 maechler 59
> 
52904 jmc 60
> x > 3 ##[1] ">.foo"
61
using >.foo
40086 ripley 62
[1] TRUE
8504 maechler 63
> 
52904 jmc 64
> rm(list=">.foo")
65
> x > 3 #-> "Ops.foo" and ">.bar"
66
using Ops.foo
67
using >.bar
40086 ripley 68
[1] FALSE
8504 maechler 69
> 
70
> 
71
> 
52904 jmc 72
> ### ------------  was ./mode-methods.R till R ver. 1.0.x ----------------
8504 maechler 73
> 
52904 jmc 74
> ###-- Using Method Dispatch on "mode" etc :
75
> ## Tests S3 dispatch with the class attr forced to be data.class
76
> ## Not very relevant when S4 methods are around, but kept for historical interest
77
> abc <- function(x, ...) {
78
+     cat("abc: Before dispatching; x has class `", class(x), "':", sep="")
79
+     str(x)
80
+     UseMethod("abc", x) ## UseMethod("abc") (as in S) fails
8504 maechler 81
+ }
82
> 
52904 jmc 83
> abc.default <- function(x, ...) sys.call()
8504 maechler 84
> 
52904 jmc 85
> "abc.(" <- function(x)
86
+     cat("'(' method of abc:", deparse(sys.call(sys.parent())),"\n")
87
> abc.expression <- function(x)
88
+     cat("'expression' method of abc:", deparse(sys.call(sys.parent())),"\n")
8504 maechler 89
> 
52904 jmc 90
> abc(1)
91
abc: Before dispatching; x has class `numeric': num 1
92
abc.default(1)
93
> e0 <- expression((x))
94
> e1 <- expression(sin(x))
95
> abc(e0)
96
abc: Before dispatching; x has class `expression':  expression((x))
97
'expression' method of abc: abc.expression(e0) 
98
> abc(e1)
99
abc: Before dispatching; x has class `expression':  expression(sin(x))
100
'expression' method of abc: abc.expression(e1) 
101
> abc(e0[[1]])
73270 maechler 102
abc: Before dispatching; x has class `(': language, mode "(": (x)
52904 jmc 103
'(' method of abc: `abc.(`(e0[[1]]) 
104
> abc(e1[[1]])
105
abc: Before dispatching; x has class `call': language sin(x)
106
abc.default(e1[[1]])
8504 maechler 107
> 
83997 luke 108
> 
84105 luke 109
> ## Some tests for `nameOfClass()`, called from inherits()
110
> ClassX <- structure(list(), name = "ClassX",
111
+                     class = c("S3pp_class", "S3pp_object"))
112
> 
113
> classx_instance <- structure(list(), class = c("ClassX", "S3pp_object"))
114
> 
115
> nameOfClass.S3pp_class <- function(x) attr(x, "name", TRUE)
116
> nameOfClass.foo <- function(x) "bar"
117
> 
118
> stopifnot(exprs = {
119
+     inherits(classx_instance, "ClassX")
120
+     inherits(classx_instance, ClassX)
121
+     ## ignore class on a character object
122
+     isTRUE(inherits(1, structure("numeric", class = "foo")))
123
+     ## make sure class is nor evaluated in calling nameOfClass
124
+     isFALSE(inherits(1, structure(quote(stop("should not be evaluated")),
125
+                                   class = "foo")))
126
+ })
127
> 
128
> 
83997 luke 129
> ## Some tests for `@` dispatching
130
> ## make sure that
131
> ## - `@` evals the first args only once,
132
> ## -  doesn't dispatch for S4
133
> ## -  works on `.Data` even for nonS4 objects
134
> 
135
> x <- structure(list(), class = "foo", prop1 = 'prop1val')
136
> registerS3method("@", "foo",
137
+     function(x, name) {
138
+         stopifnot(typeof(name) == "character", length(name) == 1L)
139
+         cat(sprintf("called `@.foo`(x = %s, name = '%s')\n",
140
+                      deparse1(substitute(x), "\n"), name))
141
+         attr(x, name, TRUE)
142
+     }
143
+ )
144
> x@prop1
145
called `@.foo`(x = x, name = 'prop1')
146
[1] "prop1val"
147
> 
148
> abc <- x
149
> abc@prop1
150
called `@.foo`(x = abc, name = 'prop1')
151
[1] "prop1val"
152
> 
153
> {
154
+     cat("new x\n")
155
+     structure(list(), class = "foo", prop1 = 'prop1val')
156
+ }@prop1
157
new x
158
called `@.foo`(x = {
159
    cat("new x\n")
160
    structure(list(), class = "foo", prop1 = "prop1val")
161
}, name = 'prop1')
162
[1] "prop1val"
163
> 
164
> makeActiveBinding("ax", function(x) {
165
+     cat("evaluating ax\n")
166
+     get("x", envir = parent.frame())
167
+ }, environment())
168
> 
169
> ax@prop1
170
evaluating ax
171
called `@.foo`(x = ax, name = 'prop1')
172
[1] "prop1val"
173
> 
174
> stopifnot(exprs = {
175
+     identical( x@prop1, "prop1val")
176
+     identical(ax@prop1, "prop1val")
177
+ 
178
+     identical(letters@.Data, letters)
179
+ })
180
called `@.foo`(x = x, name = 'prop1')
181
evaluating ax
182
called `@.foo`(x = ax, name = 'prop1')
183
> 
184
> try(letters@foo) # error
185
Error in letters@foo : 
186
  no applicable method for `@` applied to an object of class "character"
187
> 
188
> # doesn't dispatch for S4
189
> setClass("Person",
190
+   slots = c(
191
+     name = "character",
192
+     age = "numeric"
193
+   )
194
+ )
195
> 
196
> `@.Person` <- function(x, name) {
197
+   stop("called @.Person()\n")
198
+ }
199
> 
200
> p <- new("Person", name = "Who", age = -1)
201
> stopifnot(p@name == "Who")
202
> 
84107 luke 203
> 
204
> ## Some tests for `chooseOpsMethod()`, called from C DispatchGroup() when
205
> ## 2 methods are found
206
> foo_obj <- structure(1, class = "foo")
207
> bar_obj <- structure(1, class = "bar")
208
> 
209
> `+.foo` <- function(e1, e2) "foo"
210
> `+.bar` <- function(e1, e2) "bar"
211
> 
212
> invisible(foo_obj + bar_obj)  # Warning: Incompatible methods
213
Warning message:
214
Incompatible methods ("+.foo", "+.bar") for "+" 
215
> 
216
> chooseOpsMethod.bar <- function(x, y, mx, my, cl, reverse) TRUE
217
> 
218
> stopifnot(exprs = {
219
+     identical(foo_obj + bar_obj, "bar")
220
+     identical(bar_obj + foo_obj, "bar")
221
+ })
222
>