I think you need a reprex... I don't think your claim is correct as stated. On December 2, 2021 1:00:01 PM PST, Ivan Krylov <krylov.r00t at gmail.com> wrote:>Sorry for sending an unfinished message! > >On Thu, 2 Dec 2021 23:57:11 +0300 >Ivan Krylov <krylov.r00t at gmail.com> wrote: > >> Why can I forward missing i,j to built-in `[` > >Why can I forward missing i,j to the built-in `[` method but not >to user-defined methods? How can I fix this? Default i and j to TRUE? >Are there less involved methods of handling my problem of subsetting >attr(x, 'foo') with the dimnames of x? Preferrably without setting >dimnames on attr(x, 'foo') itself. >-- Sent from my phone. Please excuse my brevity.
On Thu, 02 Dec 2021 13:41:52 -0800 Jeff Newmiller <jdnewmil at dcn.davis.ca.us> wrote:> I think you need a reprex... I don't think your claim is correct as > stated.Sorry, let me try again. The following "works" for me in the sense of throwing the same error on R 3.3 and R-devel: foo <- function(x, ...) UseMethod('foo') # foo is a matrix tagged with a vector of length() == nrow(foo) foo.matrix <- function(x, y, ...) { stopifnot( !is.recursive(y), length(y) == nrow(x), length(list(...)) == 0 ) structure(x, class = 'foo', foo = y) } # the vector must be subsetted at the same time as x `[.foo` <- function(x, i, j, ..., drop = TRUE) { ret <- NextMethod() # could drop dimensions if (is.matrix(ret)) foo( ret, unname(setNames(attr(x, 'foo'), dimnames(x)[[1]])[i]) ) else ret } `[<-.foo` <- function(x, i, j, ..., value) { xsub <- x[i, j, drop = FALSE] # TODO: some checks on xsub NextMethod() } x <- foo(volcano, 1:nrow(volcano)) invisible(x[]) # doesn't stop despite missing i x[] <- 1 # fails in `[.foo` with "i missing" # Error in NextMethod() : argument "i" is missing, with no default traceback() # 9: NextMethod() at foo.R#15 # 8: `[.foo`(x, i, j, drop = FALSE) at foo.R#24 # 7: x[i, j, drop = FALSE] at foo.R#24 # 6: `[<-.foo`(`*tmp*`, , value = 1) at foo.R#30 # 5: `[<-`(`*tmp*`, , value = 1) at foo.R#30 # 4: eval(ei, envir) # 3: eval(ei, envir) # 2: withVisible(eval(ei, envir)) # 1: source("foo.R", echo = TRUE) Or did you mean some other claim? -- Best regards, Ivan
Got some progress on this, but still not sure how to continue. First, a
much more simple script reproducing the behaviour that confuses me:
foo <- function(x, ...) structure(x, class = 'foo')
`[.foo` <- function(x, i, ..., drop = TRUE) {
print(sys.call())
print(match.call())
foo(NextMethod()) # x[] should return an object of class foo
}
`[<-.foo` <- function(x, i, ..., value) {
print(sys.call())
print(match.call())
x[i, ..., drop = FALSE]
# imagine that we need to perform some checks on the
# subset of x that we're about to replace
NextMethod()
}
x <- foo(42)
x[] # this works
x[] <- 1 # this doesn't
Now, the crucial difference between the x[] and x[] <- 1 calls is that
in the former case, the `i` argument isn't even specified:
x[]
# `[.foo`(x, )
# `[.foo`(x = x)
# [1] 42
# attr(,"class")
# [1] "foo"
While in the latter case, `i` is specified in the x[] call (but
missing):
x[] <- 1
# `[<-.foo`(`*tmp*`, , value = 1)
# `[<-.foo`(x = `*tmp*`, value = 1)
# x[i, ..., drop = FALSE]
# `[.foo`(x = x, i = i, drop = FALSE)
Error in NextMethod() : argument "i" is missing, with no default
What's the best way to forward the arguments from [<-.class methods to
the [.class methods in order to handle cases like x[] properly?
--
Best regards,
Ivan