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 ______________________________________________ R-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel