-
Notifications
You must be signed in to change notification settings - Fork 57
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
loss of class on S4 dispatch error #209
Comments
It looks like the e <- new.env()
class(e) <- c("a", "b")
structure(e, class = "c")
e
#> <environment: 0x7fd48b6a8560>
#> attr(,"class")
#> [1] "c"
The particular issue you're running into with jsonlite is because I don't think this particular issue with In the example below, suppose one person writes inc_val <- function(x) {
x$val <- x$val + 1
x
}
a <- new.env()
a$val <- 1
inc_val(a)
a$val
#> [1] 2 |
I guess this is simply a risk with reference classes (and similars), but I wonder if there's a way to detect these unintended/unexpected consequences of some how some functions are implemented. Like a pre- and post-call result <- expect_no_change(x, f, ...) ... where More generally, I wonder how many such functions are out there, especially how many might conditionally modify an argument in place, which would be harder to reliably detect ahead of time. I suppose it's not too common the case that a users' R6 objects will be passed as args into someone else's functions, with the big exception being generics. In my case, I detected this because of my attempt to build a superclass generic-handler for when my R6 objects are nested in some other structure (e.g. a list) and I want to
That pattern above works (i.e. the Parent's asJSON method is ultimately dispatched), but I think any S3 generic's |
Edited for simplicity with the root issue. Here I create a R6 class (generator) and an object instance. Then call
structure(...)
on that instance, which apparently modifies the original object in place:Output:
Now,
structure
it:And let's examine
x
:Output:
In spirit I understand why this is happening, as it appears
structure
modifiesx
in place (i.e. with reference semantics).structure
's man page is (to me?) a bit ambiguous about this, with:And I can't find anything the R6 docs issuing a warning about this. It manifested with jsonlite's
asJSON
class-based delegation here. With a non-R6 object the original object remains unchanged after walking through that recursive conditional dispatching code with repeated failures and the incremental class 'stripping' (here):Output:
Is this worth a mention/warning in the R6 documentation? I do realize it's up to the class author to carefully manage to which functions she might be passing an R6 object, but given that
asJSON
had no immediate knowledge of the inner structure of this R6 object (i.e.asJSON
wasn't calling anyactive
orpublic
R6 method), it was quite surprising to find the object had been mutated.The text was updated successfully, but these errors were encountered: