From murdoch@dunc@n @end|ng |rom gm@||@com  Sun Nov  3 22:31:23 2019
From: murdoch@dunc@n @end|ng |rom gm@||@com (Duncan Murdoch)
Date: Sun, 3 Nov 2019 16:31:23 -0500
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: <b795d8d3-d20b-0576-9d8d-011307e51707@gmail.com>

On 03/11/2019 4:11 p.m., Rolf Turner 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?

Defaults for parameters are evaluated in the evaluation frame of the 
function, at the time the parameter is first used.

If you look at the source for "[.data.frame", you should see that "cols" 
is defined there as a local variable.  The "drop" argument shouldn't be 
used until it is.  (There's a call to "missing(drop)" early in the 
source that doesn't count:  it doesn't evaluate "drop", it just checks 
whether it is specified by the caller.)

Duncan Murdoch



[Rd] Puzzled about a new method for "[".
Duncan Murdoch