Martin Maechler
2016-Mar-07 17:26 UTC
[Rd] body(NULL) <- something; ditto formals() -- should not work
I'm proposing to signal an error (from R >= 3.3.0) in such examples -- which do "work" in R 3.2.x and earlier :> f <- NULL; body(f) <- quote(sin(a+1)); ffunction () sin(a + 1) <environment: 0x48f9798>> g <- NULL; formals(g) <- alist(x = pi, y=); gfunction (x = pi, y) NULL <environment: 0x4e6dfe8>>The proposal is that the underlying C code will signal an error when such replacement functions would create a function out of "something not a function". Martin Maechler, ETH Zurich
Hervé Pagès
2016-Mar-29 19:19 UTC
[Rd] body(NULL) <- something; ditto formals() -- should not work
Hi, On 03/07/2016 09:26 AM, Martin Maechler wrote:> I'm proposing to signal an error (from R >= 3.3.0) in such > examples -- which do "work" in R 3.2.x and earlier : > >> f <- NULL; body(f) <- quote(sin(a+1)); f > function () > sin(a + 1) > <environment: 0x48f9798> >This works because formals() (the getter) works on things that are not a function.>> g <- NULL; formals(g) <- alist(x = pi, y=); g > function (x = pi, y) > NULL > <environment: 0x4e6dfe8> >>And this works because body() (the getter) also works on things that are not a function.> > The proposal is that the underlying C code will signal an error > when such replacement functions would create a function out of > "something not a function".Why modify the C code for this? This is how formals() and body() are defined at the moment: > formals function (fun = sys.function(sys.parent())) { if (is.character(fun)) fun <- get(fun, mode = "function", envir = parent.frame()) .Internal(formals(fun)) } <bytecode: 0x153cde0> <environment: namespace:base> > body function (fun = sys.function(sys.parent())) { if (is.character(fun)) fun <- get(fun, mode = "function", envir = parent.frame()) .Internal(body(fun)) } <bytecode: 0xb452e8> <environment: namespace:base> Not sure why they are not simply doing fun <- match.fun(fun) but if they were, then they would signal an error when called on something that is not a function. H.> > Martin Maechler, ETH Zurich > > ______________________________________________ > R-devel at r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-devel >-- Herv? Pag?s Program in Computational Biology Division of Public Health Sciences Fred Hutchinson Cancer Research Center 1100 Fairview Ave. N, M1-B514 P.O. Box 19024 Seattle, WA 98109-1024 E-mail: hpages at fredhutch.org Phone: (206) 667-5791 Fax: (206) 667-1319
Martin Maechler
2016-Mar-30 07:55 UTC
[Rd] body(NULL) <- something; ditto formals() -- should not work
>>>>> Herv? Pag?s <hpages at fredhutch.org> >>>>> on Tue, 29 Mar 2016 12:19:12 -0700 writes:> Hi, > On 03/07/2016 09:26 AM, Martin Maechler wrote: >> I'm proposing to signal an error (from R >= 3.3.0) in such >> examples -- which do "work" in R 3.2.x and earlier : >> >>> f <- NULL; body(f) <- quote(sin(a+1)); f >> function () >> sin(a + 1) >> <environment: 0x48f9798> >> > This works because formals() (the getter) works on things that are > not a function. >>> g <- NULL; formals(g) <- alist(x = pi, y=); g >> function (x = pi, y) >> NULL >> <environment: 0x4e6dfe8> >>> > And this works because body() (the getter) also works on things that > are not a function. of course (twice). >> The proposal is that the underlying C code will signal an error >> when such replacement functions would create a function out of >> "something not a function". > Why modify the C code for this? My current proposal would change both the C code *and* the following. > This is how formals() and body() are defined at the moment: >> formals > function (fun = sys.function(sys.parent())) > { > if (is.character(fun)) > fun <- get(fun, mode = "function", envir = parent.frame()) > .Internal(formals(fun)) > } > <bytecode: 0x153cde0> > <environment: namespace:base> >> body > function (fun = sys.function(sys.parent())) > { > if (is.character(fun)) > fun <- get(fun, mode = "function", envir = parent.frame()) > .Internal(body(fun)) > } > <bytecode: 0xb452e8> > <environment: namespace:base> > Not sure why they are not simply doing fun <- match.fun(fun) but if > they were, then they would signal an error when called on something > that is not a function. Using match.fun() will probably be "the right thing" in the future. However, as this has been an unchanged part of R for very many years, my current proposal would only signal *warnings* for now. Thank you, Herve, for the reminder about this. Indeed, I *have* been wanting to commit my proposal to R-devel for a long time and somehow have always been anxious to produce too many negative effects with CRAN / Bioconductor packages producing warning (or errors) after the change and me not having the time to send e-mails to all the package maintainers. As I won't have time for that anyway, and as "good package maintainers" should at least browse, if not read the R-devel mailing list (;-), your prompting now makes me commit my proposal (to R-devel only; *not* R 3.4.0 alpha) and leave the resulting "problems" to the package maintainers affected. Martin