From maechler at stat.math.ethz.ch  Wed Mar 30 09:55:54 2016
From: maechler at stat.math.ethz.ch (Martin Maechler)
Date: Wed, 30 Mar 2016 09:55:54 +0200
Subject: [Rd] body(NULL) <- something; ditto formals() -- should not work
In-Reply-To: <56FAD530.50104@fredhutch.org>
References: <22237.47553.217160.571753@stat.math.ethz.ch>
	<56FAD530.50104@fredhutch.org>
Message-ID: <22267.34442.773963.56719@stat.math.ethz.ch>

>>>>> 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



[Rd] body(NULL) <- something; ditto formals() -- should not work
Martin Maechler