| 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 |
>
|