From h@w|ckh@m @end|ng |rom gm@||@com  Mon Nov  4 15:41:59 2019
From: h@w|ckh@m @end|ng |rom gm@||@com (Hadley Wickham)
Date: Mon, 4 Nov 2019 08:41:59 -0600
Subject: [Rd] Puzzled about a new method for "[".
In-Reply-To: <74a6cf10-3266-fef8-9ea0-0ba6d36db807@auckland.ac.nz>
References: <74a6cf10-3266-fef8-9ea0-0ba6d36db807@auckland.ac.nz>
Message-ID: <CABdHhvFZ2VL27iJb_hZmMK1Tmxq1gZKu7np1fNjk9F2KM2ME8Q@mail.gmail.com>

For what it's worth, I don't think this strategy can work in general,
because a class might have attributes that depend on its data/contents
(e.g. https://vctrs.r-lib.org/articles/s3-vector.html#cached-sum). I
don't think these are particularly common in practice, but it's
dangerous to assume that you can restore a class simply by restoring
its attributes after subsetting.

Hadley

On Sun, Nov 3, 2019 at 3:11 PM Rolf Turner <r.turner at auckland.ac.nz> wrote:
>
>
> I recently tried to write a new method for "[", to be applied to data
> frames, so that the object returned would retain (all) attributes of the
> columns, including attributes that my code had created.
>
> I thrashed around for quite a while, and then got some help from Rui
> Barradas who showed me how to do it, in the following manner:
>
> `[.myclass` <- function(x, i, j, drop = if (missing(i)) TRUE else
> length(cols) == 1)[{
>     SaveAt <- lapply(x, attributes)
>     x <- NextMethod()
>     lX <- lapply(names(x),function(nm, x, Sat){
>       attributes(x[[nm]]) <- Sat[[nm]]
>       x[[nm]]}, x = x, Sat = SaveAt)
>     names(lX) <- names(x)
>     x <- as.data.frame(lX)
>     x
> }
>
> If I set class(X) <- c("myclass",class(X)) and apply "[" to X (e.g.
> something like X[1:42,]) the attributes are retained as desired.
>
> OK.  All good.  Now we finally come to my question!  I want to put this
> new method into a package that I am building.  When I build the package
> and run R CMD check I get a complaint:
>
> ... no visible binding for global variable ?cols?
>
> And indeed, there is no such variable.  At first I thought that maybe
> the code should be
>
> `[.myclass` <- function(x, i, j, drop = if (missing(i)) TRUE else
>                                        length(j) == 1)[{
>
> But I looked at "[.data.frame" and it has "cols" too; not "j".
>
> So why doesn't "[.data.frame" throw a warning when R gets built?
>
> Can someone please explain to me what's going on here?
>
> cheers,
>
> Rolf
>
> P. S. I amended the code for my method, replacing "cols" by "j", and it
> *seems* to run, and deliver the desired results.  (And the package
> checks, without complaint.) I am nervous, however, that there may be
> some Trap for Young Players that I don't perceive, lurking about and
> waiting to cause problems for me.
>
> R.
>
> --
> Honorary Research Fellow
> Department of Statistics
> University of Auckland
> Phone: +64-9-373-7599 ext. 88276
>
> ______________________________________________
> R-devel at r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel



-- 
http://hadley.nz



[Rd] Puzzled about a new method for "[".
Hadley Wickham