Dear All,
In R 3.6.3 (and earlier), method dispatch used to work for methods stored in local environments that are attached to the search path. For example:
myfun <- function(y) {
out <- list(y=y)
class(out) <- "myclass"
return(out)
}
print.myclass <- function(x, ...) print(formatC(x$y, format="f", digits=5))
myfun(1:4)
# prints: [1] "1.00000" "2.00000" "3.00000" "4.00000"
rm(print.myclass)
myenv <- new.env()
myenv$print.myclass <- local(function(x, ...) print(formatC(x$y, format="f", digits=5)), myenv)
attach(myenv)
myfun(1:4)
# still prints: [1] "1.00000" "2.00000" "3.00000" "4.00000"
But since R 4.0.0, this no longer words and the above prints:
$y
[1] 1 2 3 4
attr(,"class")
[1] "myclass"
Is this intended? And is there a way to still make this work?
Best,
Wolfgang
S3 method dispatch for methods in local environments
5 messages · Martin Maechler, Wolfgang Viechtbauer, Sebastian Meyer
Viechtbauer, Wolfgang (SP)
on Tue, 12 May 2020 18:05:32 +0000 writes:
> Dear All,
> In R 3.6.3 (and earlier), method dispatch used to work for methods stored in local environments that are attached to the search path. For example:
> myfun <- function(y) {
> out <- list(y=y)
> class(out) <- "myclass"
> return(out)
> }
> print.myclass <- function(x, ...) print(formatC(x$y, format="f", digits=5))
> myfun(1:4)
> # prints: [1] "1.00000" "2.00000" "3.00000" "4.00000"
> rm(print.myclass)
> myenv <- new.env()
> myenv$print.myclass <- local(function(x, ...) print(formatC(x$y, format="f", digits=5)), myenv)
> attach(myenv)
> myfun(1:4)
> # still prints: [1] "1.00000" "2.00000" "3.00000" "4.00000"
> But since R 4.0.0, this no longer words and the above prints:
> $y
> [1] 1 2 3 4
> attr(,"class")
> [1] "myclass"
> Is this intended?
yes, most probably, unless
> And is there a way to still make this work?
Using the new
.S3method(<generic>, <class>, <method_function>)
had been intended as substitute. Can you try it with your
attached-environment (which makes sense!) approach ?
Best,
Martin
Indeed, that works:
myfun <- function(y) {
out <- list(y=y)
class(out) <- "myclass"
return(out)
}
myenv <- new.env()
myenv$print.myclass <- local(function(x, ...) print(formatC(x$y, format="f", digits=5)), new.env(myenv))
.S3method("print", "myclass", myenv$print.myclass)
attach(myenv)
myfun(1:4)
# [1] "1.00000" "2.00000" "3.00000" "4.00000"
Thanks for the tip!
Best,
Wolfgang
-----Original Message----- From: Martin Maechler [mailto:maechler at stat.math.ethz.ch] Sent: Tuesday, 12 May, 2020 21:05 To: Viechtbauer, Wolfgang (SP) Cc: r-devel (r-devel at r-project.org) Subject: Re: [Rd] S3 method dispatch for methods in local environments
Viechtbauer, Wolfgang (SP)
on Tue, 12 May 2020 18:05:32 +0000 writes:
> Dear All, > In R 3.6.3 (and earlier), method dispatch used to work for methods
stored in local environments that are attached to the search path. For example:
> myfun <- function(y) {
> out <- list(y=y)
> class(out) <- "myclass"
> return(out)
> }
> print.myclass <- function(x, ...) print(formatC(x$y, format="f",
digits=5))
> myfun(1:4)
> # prints: [1] "1.00000" "2.00000" "3.00000" "4.00000"
> rm(print.myclass) > myenv <- new.env() > myenv$print.myclass <- local(function(x, ...) print(formatC(x$y,
format="f", digits=5)), myenv)
> attach(myenv) > myfun(1:4)
> # still prints: [1] "1.00000" "2.00000" "3.00000" "4.00000"
> But since R 4.0.0, this no longer words and the above prints:
> $y > [1] 1 2 3 4
> attr(,"class") > [1] "myclass"
> Is this intended?
yes, most probably, unless
> And is there a way to still make this work?
Using the new
.S3method(<generic>, <class>, <method_function>)
had been intended as substitute. Can you try it with your
attached-environment (which makes sense!) approach ?
Best,
Martin
Dear Wolfgang, I think this new behaviour is related to the following R 4.0.0 NEWS item:
S3 method lookup now by default skips the elements of the search path between the global and base environments.
Your environment "myenv" is attached at position 2 of the search() path
and thus now skipped in S3 method lookup.
I have just noticed that
attr(methods(class="myclass"), "info")
getS3method("print", "myclass")
both still find your function in myenv although the generic's
UseMethod() won't. I find this a bit confusing.
A solution to make R >= 4.0.0 find your method is to register the S3
method using the new function .S3method (intended for R scripts, not
packages). After running
.S3method("print", "myclass", myenv$print.myclass)
your method will be found from the generic.
Best regards,
Sebastian
Am 12.05.20 um 20:05 schrieb Viechtbauer, Wolfgang (SP):
Dear All,
In R 3.6.3 (and earlier), method dispatch used to work for methods stored in local environments that are attached to the search path. For example:
myfun <- function(y) {
out <- list(y=y)
class(out) <- "myclass"
return(out)
}
print.myclass <- function(x, ...) print(formatC(x$y, format="f", digits=5))
myfun(1:4)
# prints: [1] "1.00000" "2.00000" "3.00000" "4.00000"
rm(print.myclass)
myenv <- new.env()
myenv$print.myclass <- local(function(x, ...) print(formatC(x$y, format="f", digits=5)), myenv)
attach(myenv)
myfun(1:4)
# still prints: [1] "1.00000" "2.00000" "3.00000" "4.00000"
But since R 4.0.0, this no longer words and the above prints:
$y
[1] 1 2 3 4
attr(,"class")
[1] "myclass"
Is this intended? And is there a way to still make this work?
Best,
Wolfgang
______________________________________________ R-devel at r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel
Thanks, Sebastian, for the pointer to the NEWS item. After some further search, I also found this in the R Blog: https://developer.r-project.org/Blog/public/2019/08/19/s3-method-lookup/ Best, Wolfgang
-----Original Message----- From: R-devel [mailto:r-devel-bounces at r-project.org] On Behalf Of Sebastian Meyer Sent: Tuesday, 12 May, 2020 21:17 To: r-devel at r-project.org Subject: Re: [Rd] S3 method dispatch for methods in local environments Dear Wolfgang, I think this new behaviour is related to the following R 4.0.0 NEWS item:
S3 method lookup now by default skips the elements of the search path
between the global and base environments.
Your environment "myenv" is attached at position 2 of the search() path
and thus now skipped in S3 method lookup.
I have just noticed that
attr(methods(class="myclass"), "info")
getS3method("print", "myclass")
both still find your function in myenv although the generic's
UseMethod() won't. I find this a bit confusing.
A solution to make R >= 4.0.0 find your method is to register the S3
method using the new function .S3method (intended for R scripts, not
packages). After running
.S3method("print", "myclass", myenv$print.myclass)
your method will be found from the generic.
Best regards,
Sebastian
Am 12.05.20 um 20:05 schrieb Viechtbauer, Wolfgang (SP):
Dear All, In R 3.6.3 (and earlier), method dispatch used to work for methods stored
in local environments that are attached to the search path. For example:
myfun <- function(y) {
out <- list(y=y)
class(out) <- "myclass"
return(out)
}
print.myclass <- function(x, ...) print(formatC(x$y, format="f",
digits=5))
myfun(1:4) # prints: [1] "1.00000" "2.00000" "3.00000" "4.00000" rm(print.myclass) myenv <- new.env() myenv$print.myclass <- local(function(x, ...) print(formatC(x$y,
format="f", digits=5)), myenv)
attach(myenv) myfun(1:4) # still prints: [1] "1.00000" "2.00000" "3.00000" "4.00000" But since R 4.0.0, this no longer words and the above prints: $y [1] 1 2 3 4 attr(,"class") [1] "myclass" Is this intended? And is there a way to still make this work? Best, Wolfgang