Re: [R] Forwarding missing arguments to the `[` method
On Thu, 9 Dec 2021 15:47:02 +0100 Martin Maechler wrote: > What you should take from there: > Do work with *both* > missing(drop) > and > nargs() > > (and more) > in order to distinguish m[i] from m[i,] etc Thanks for the advice! `[<-.data.frame` does make for enlightening reading. I've also considered editing the call, like lm() does: `[<-.foo` <- function(x, i, ..., value) { cl <- match.call(expand.dots = FALSE) cl[[1L]] <- quote(`[`) cl$value <- NULL x.subset <- eval(cl, parent.frame()) # ... checks on x.subset ... NextMethod() } ...but that fails _some_ of my tests (but not others) with "object `*tmp*` not found"). Non-standard evaluation is probably not the answer here. I'll have to handle the forms of the call with different nargs() manually and separately. -- Best regards, Ivan __ R-help@r-project.org mailing list -- To UNSUBSCRIBE and more, see https://stat.ethz.ch/mailman/listinfo/r-help PLEASE do read the posting guide http://www.R-project.org/posting-guide.html and provide commented, minimal, self-contained, reproducible code.
Re: [R] Forwarding missing arguments to the `[` method
> Ivan Krylov > on Wed, 8 Dec 2021 16:52:00 +0300 writes: I have always learnt a lot about programming when reading other people's code .. notably if those people new what they are doing. In this case, studying R-core's `[.data.frame` and `[<-.data.frame` {or for S4 methods, the 'Matrix' or 'Rmpfr' packages} should show you a lot. What you should take from there: Do work with *both* missing(drop) and nargs() (and more) in order to distinguish m[i] from m[i,] etc Best, Martin > 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 > > __ __ R-help@r-project.org mailing list -- To UNSUBSCRIBE and more, see https://stat.ethz.ch/mailman/listinfo/r-help PLEASE do read the posting guide http://www.R-project.org/posting-guide.html and provide commented, minimal, self-contained, reproducible code.
Re: [R] Forwarding missing arguments to the `[` method
I haven't followed this thread, so this may be stupid, but have you looked at the do.call(`[`,...) idiom? Something like: x <- array(1:8, c(2,2,2)) > x , , 1 [,1] [,2] [1,]13 [2,]24 , , 2 [,1] [,2] [1,]57 [2,]68 > l <- as.list(rep(TRUE, 2)) > do.call(`[`, c(list(x), l, list(1, drop = TRUE))) [,1] [,2] [1,]13 [2,]24 Feel free to ignore without comment if this is unhelpful. Bert Gunter Bert Gunter "The trouble with having an open mind is that people keep coming along and sticking things into it." -- Opus (aka Berkeley Breathed in his "Bloom County" comic strip ) On Wed, Dec 8, 2021 at 5:52 AM Ivan Krylov wrote: > > 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 > > __ > R-help@r-project.org mailing list -- To UNSUBSCRIBE and more, see > https://stat.ethz.ch/mailman/listinfo/r-help > PLEASE do read the posting guide http://www.R-project.org/posting-guide.html > and provide commented, minimal, self-contained, reproducible code. __ R-help@r-project.org mailing list -- To UNSUBSCRIBE and more, see https://stat.ethz.ch/mailman/listinfo/r-help PLEASE do read the posting guide http://www.R-project.org/posting-guide.html and provide commented, minimal, self-contained, reproducible code.
Re: [R] Forwarding missing arguments to the `[` method
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 __ R-help@r-project.org mailing list -- To UNSUBSCRIBE and more, see https://stat.ethz.ch/mailman/listinfo/r-help PLEASE do read the posting guide http://www.R-project.org/posting-guide.html and provide commented, minimal, self-contained, reproducible code.
Re: [R] Forwarding missing arguments to the `[` method
On Thu, 02 Dec 2021 13:41:52 -0800 Jeff Newmiller 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 __ R-help@r-project.org mailing list -- To UNSUBSCRIBE and more, see https://stat.ethz.ch/mailman/listinfo/r-help PLEASE do read the posting guide http://www.R-project.org/posting-guide.html and provide commented, minimal, self-contained, reproducible code.
Re: [R] Forwarding missing arguments to the `[` method
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 wrote: >Sorry for sending an unfinished message! > >On Thu, 2 Dec 2021 23:57:11 +0300 >Ivan Krylov 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. __ R-help@r-project.org mailing list -- To UNSUBSCRIBE and more, see https://stat.ethz.ch/mailman/listinfo/r-help PLEASE do read the posting guide http://www.R-project.org/posting-guide.html and provide commented, minimal, self-contained, reproducible code.
[R] Forwarding missing arguments to the `[` method
Hi everyone, Suppose I've got a class 'foo' that's a matrix tagged with a vector of length() == nrow(foo): foo <- function(x, ...) UseMethod('foo') foo.matrix <- function(x, y, ...) { stopifnot( !is.recursive(y), length(y) == nrow(x), length(list(...)) == 0 ) structure(x, class = 'foo', foo = y) } The invariant that the vector follows the rows of the matrix must be maintained, so I write a [.foo method: `[.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 } Note the acrobatics required to handle indexing objects of class foo by the dimnames of the matrix. If I used foo(attr(x,'foo')[i]) instead, indexing by dimnames would result in the correct subset of the matrix tagged with a vector of NAs. Now I would like to implement sub-assignment. I would like to access the correct subset of the 'foo' vector (for example, if value is also of class foo, I would like to check if the 'foo' attributes match between value and x), but I don't want to copy the code or create a separate method, so I call `[.foo` instead: `[<-.foo` <- function(x, i, j, ..., value) { xsub <- x[i,j] # safety checks on attr(xsub, 'foo') NextMethod() } ...except this doesn't quite work: x <- foo(volcano, 1:nrow(volcano)) x[] <- 1 # Error in NextMethod() : argument "i" is missing, with no default traceback() # 5: NextMethod() at foo.R#15 # 4: `[.foo`(x, i, j) at foo.R#24 # 3: x[i, j] at foo.R#24 # 2: `[<-.foo`(`*tmp*`, , value = 1) # 1: `[<-`(`*tmp*`, , value = 1) Why can I forward missing i,j to built-in `[` -- Best regards, Ivan __ R-help@r-project.org mailing list -- To UNSUBSCRIBE and more, see https://stat.ethz.ch/mailman/listinfo/r-help PLEASE do read the posting guide http://www.R-project.org/posting-guide.html and provide commented, minimal, self-contained, reproducible code.
Re: [R] Forwarding missing arguments to the `[` method
Sorry for sending an unfinished message! On Thu, 2 Dec 2021 23:57:11 +0300 Ivan Krylov 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. -- Best regards, Ivan __ R-help@r-project.org mailing list -- To UNSUBSCRIBE and more, see https://stat.ethz.ch/mailman/listinfo/r-help PLEASE do read the posting guide http://www.R-project.org/posting-guide.html and provide commented, minimal, self-contained, reproducible code.