Hi all, I believe there is an issue with passing NULL to the function I(). class(NULL) # "NULL" (as expected) print(NULL) # NULL (as expected) is.null(NULL) # TRUE (as expected) According to the documentation I() should return a copy of its input with class "AsIs" preprended: class(I(NULL)) # "AsIs" (as expected) print(I(NULL)) # list() (not expected! should be NULL) is.null(I(NULL)) # FALSE (not expected! should be TRUE) So, I() does not behave according to its documentation. In R, it is not possible to give NULL attributes, but I(NULL) attempts to do that nonetheless, using the structure() function. Probably: 1/ structure() should not accept NULL as input since the goal of structure() is to set some attributes, something cannot be done on NULL. 2/ I() could accept NULL, but, as an exception, not set an "AsIs" class attribute on it. This would be in line with the philosophy of the I() function to return an object that is functionally equivalent to the input object. My sessionInfo() returns:> sessionInfo()R version 3.3.2 (2016-10-31) Platform: x86_64-w64-mingw32/x64 (64-bit) Running under: Windows 7 x64 (build 7601) Service Pack 1 locale: [1] LC_COLLATE=German_Switzerland.1252 LC_CTYPE=German_Switzerland.1252 LC_MONETARY=German_Switzerland.1252 LC_NUMERIC=C [5] LC_TIME=German_Switzerland.1252 attached base packages: [1] stats graphics grDevices utils datasets methods base Best regards, Florent
>>>>> Florent Angly <florent.angly at gmail.com> >>>>> on Tue, 20 Dec 2016 13:42:37 +0100 writes:> Hi all, > I believe there is an issue with passing NULL to the function I(). > class(NULL) # "NULL" (as expected) > print(NULL) # NULL (as expected) > is.null(NULL) # TRUE (as expected) > According to the documentation I() should return a copy of its input > with class "AsIs" preprended: > class(I(NULL)) # "AsIs" (as expected) > print(I(NULL)) # list() (not expected! should be NULL) > is.null(I(NULL)) # FALSE (not expected! should be TRUE) > So, I() does not behave according to its documentation. yes. > In R, it is > not possible to give NULL attributes, but I(NULL) attempts to do that > nonetheless, using the structure() function. Probably: > 1/ structure() should not accept NULL as input since the goal of > structure() is to set some attributes, something cannot be done on > NULL. I tend to agree. However if we gave an error now, I notice that even our own code, e.g., in stats:::formula.default() would fail. Still, I think we should consider *deprecating* structure(NULL, *), so it would give a *warning* (and continue working otherwise) (for a while before giving an error a year later). > 2/ I() could accept NULL, but, as an exception, not set an "AsIs" > class attribute on it. This would be in line with the philosophy of > the I() function to return an object that is functionally equivalent > to the input object. If we'd adopt 2, the I(.) function would become slightly more complicated and slower... but possibly not practically noticeable. A last option would be 3/ The help page for I() could note what happens in the NULL case. That would be the least work for everyone, but at the moment, I tend to agree that '1/' is worth the pain to have R's structure() become more consistent. Martin Maechler ETH Zurich > My sessionInfo() returns: >> sessionInfo() > R version 3.3.2 (2016-10-31) > Platform: x86_64-w64-mingw32/x64 (64-bit) > Running under: Windows 7 x64 (build 7601) Service Pack 1 > locale: > [1] LC_COLLATE=German_Switzerland.1252 > LC_CTYPE=German_Switzerland.1252 > LC_MONETARY=German_Switzerland.1252 LC_NUMERIC=C > [5] LC_TIME=German_Switzerland.1252 > attached base packages: > [1] stats graphics grDevices utils datasets methods base > Best regards, > Florent > ______________________________________________ > R-devel at r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-devel
Thank you for the feedback, Martin. Of course, deprecating would be a sensible way to go. I filed this issue on BugZilla under # 17198. Florent On 22 December 2016 at 10:24, Martin Maechler <maechler at stat.math.ethz.ch> wrote:>>>>>> Florent Angly <florent.angly at gmail.com> >>>>>> on Tue, 20 Dec 2016 13:42:37 +0100 writes: > > > Hi all, > > I believe there is an issue with passing NULL to the function I(). > > > class(NULL) # "NULL" (as expected) > > print(NULL) # NULL (as expected) > > is.null(NULL) # TRUE (as expected) > > > According to the documentation I() should return a copy of its input > > with class "AsIs" preprended: > > > class(I(NULL)) # "AsIs" (as expected) > > print(I(NULL)) # list() (not expected! should be NULL) > > is.null(I(NULL)) # FALSE (not expected! should be TRUE) > > > So, I() does not behave according to its documentation. > > yes. > > > In R, it is > > not possible to give NULL attributes, but I(NULL) attempts to do that > > nonetheless, using the structure() function. Probably: > > 1/ structure() should not accept NULL as input since the goal of > > structure() is to set some attributes, something cannot be done on > > NULL. > > I tend to agree. However if we gave an error now, I notice that > even our own code, e.g., in stats:::formula.default() would fail. > > Still, I think we should consider *deprecating* structure(NULL, *), > so it would give a *warning* (and continue working otherwise) > (for a while before giving an error a year later). > > > 2/ I() could accept NULL, but, as an exception, not set an "AsIs" > > class attribute on it. This would be in line with the philosophy of > > the I() function to return an object that is functionally equivalent > > to the input object. > > If we'd adopt 2, the I(.) function would become slightly more > complicated and slower... but possibly not practically > noticeable. > > A last option would be > > 3/ The help page for I() could note what happens in the NULL case. > > That would be the least work for everyone, > but at the moment, I tend to agree that '1/' is worth the pain to > have R's structure() become more consistent. > > Martin Maechler > ETH Zurich > > > My sessionInfo() returns: > >> sessionInfo() > > R version 3.3.2 (2016-10-31) > > Platform: x86_64-w64-mingw32/x64 (64-bit) > > Running under: Windows 7 x64 (build 7601) Service Pack 1 > > > locale: > > [1] LC_COLLATE=German_Switzerland.1252 > > LC_CTYPE=German_Switzerland.1252 > > LC_MONETARY=German_Switzerland.1252 LC_NUMERIC=C > > [5] LC_TIME=German_Switzerland.1252 > > > attached base packages: > > [1] stats graphics grDevices utils datasets methods base > > > Best regards, > > > Florent > > > ______________________________________________ > > R-devel at r-project.org mailing list > > https://stat.ethz.ch/mailman/listinfo/r-devel
Martin Maechler
2016-Dec-29 21:32 UTC
[Rd] structure(NULL, *) is deprecated [was: Unexpected I(NULL) output]
>>>>> Martin Maechler <maechler at stat.math.ethz.ch> >>>>> on Thu, 22 Dec 2016 10:24:43 +0100 writes:>>>>> Florent Angly <florent.angly at gmail.com> >>>>> on Tue, 20 Dec 2016 13:42:37 +0100 writes:>> Hi all, >> I believe there is an issue with passing NULL to the function I(). >> class(NULL) # "NULL" (as expected) >> print(NULL) # NULL (as expected) >> is.null(NULL) # TRUE (as expected) >> According to the documentation I() should return a copy of its input >> with class "AsIs" preprended: >> class(I(NULL)) # "AsIs" (as expected) >> print(I(NULL)) # list() (not expected! should be NULL) >> is.null(I(NULL)) # FALSE (not expected! should be TRUE) >> So, I() does not behave according to its documentation. > yes. >> In R, it is >> not possible to give NULL attributes, but I(NULL) attempts to do that >> nonetheless, using the structure() function. Probably: >> 1/ structure() should not accept NULL as input since the goal of >> structure() is to set some attributes, something cannot be done on >> NULL. > I tend to agree. However if we gave an error now, I notice that > even our own code, e.g., in stats:::formula.default() would fail. > Still, I think we should consider *deprecating* structure(NULL, *), > so it would give a *warning* (and continue working otherwise) > (for a while before giving an error a year later). [......................] > Martin Maechler > ETH Zurich Since svn rev 71841, structure(NULL, *) now __is__ deprecated in R-devel, i.e., > structure(NULL, foo = 2) list() attr(,"foo") [1] 2 Warning message: In structure(NULL, foo = 2) : Calling 'structure(NULL, *)' is deprecated, as NULL cannot have attributes. Consider 'structure(list(), *)' instead. > A dozen or so CRAN packages now not only give warnings but partially also ERRORS in their checks, which I find strange, but it may be because of too stringent checks (e.g. checks were all warnings are turned into errors). The most prominent packages now giving errors are data.table and ggplot2, then also GGally. Of course, we (the R core team) could make the deprecation even milder by not giving a warning() but only a message(.) aka "NOTE"; however, that renders the deprecation process longer and more complicated (notably for us), and there is still a few months' time before this version of R will be released... and really, as I said,... a new warning should rarely cause *errors* but rather warnings. OTOH, some of us have now seen / read on the R-package-devel mailing list that it seems ggplot2 has stopped working correctly (under R-devel only!) in building packages because of this warning.. The current plan is it will eventually, i.e., after the deprecation period, become an error, so ideally packages are patched and re-released ASAP. It's bedtime here now and we will see tomorrow how to continue. My current plan is to an e-mail to the package maintainers of CRAN packages that are affected, at least for those packages that are "easy to find". Martin Maechler, ETH Zurich