Re: [R] Forwarding missing arguments to the `[` method

2021-12-10 Thread Ivan Krylov
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

2021-12-09 Thread Martin Maechler
> 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

2021-12-08 Thread Bert Gunter
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

2021-12-08 Thread Ivan Krylov
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

2021-12-02 Thread Ivan Krylov
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

2021-12-02 Thread Jeff Newmiller
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

2021-12-02 Thread Ivan Krylov
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

2021-12-02 Thread Ivan Krylov
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.