From ggrothendieck at gmail.com  Thu Oct 26 05:43:27 2006
From: ggrothendieck at gmail.com (Gabor Grothendieck)
Date: Wed, 25 Oct 2006 23:43:27 -0400
Subject: [Rd] how to determine if a function's result is invisible
In-Reply-To: <1161832963.4556.25.camel@localhost.localdomain>
References: <971536df0610251714u451cf80fy80bf38cb2f130734@mail.gmail.com>
	<1161825632.4556.14.camel@localhost.localdomain>
	<eb555e660610251916g16502346mad5808724a0d9905@mail.gmail.com>
	<1161832963.4556.25.camel@localhost.localdomain>
Message-ID: <971536df0610252043m11995a37lebad6b1624bec8d@mail.gmail.com>

On 10/25/06, Marc Schwartz <MSchwartz at mn.rr.com> wrote:
> On Wed, 2006-10-25 at 19:16 -0700, Deepayan Sarkar wrote:
> > On 10/25/06, Marc Schwartz <MSchwartz at mn.rr.com> wrote:
> > > On Wed, 2006-10-25 at 20:14 -0400, Gabor Grothendieck wrote:
> > > > Suppose we have a function such as the following
> > > >
> > > > F <- function(f, x) f(x)+1
> > > >
> > > > which runs function f and then transforms it.  I would like the
> > > > corresponding function which works the same except that
> > > > unlike F returns an invisible result if and only if f does.
> > > >
> > > > Is there some way of determining whether f returns
> > > > an invisible result or not?
> > > >
> > > > Thus we want this:
> > > >
> > > > f <- function(x) x
> > > > g <- function(x) invisible(x)
> > > >
> > > > > F(f, 1)
> > > > 2
> > > > >
> > > >
> > > > > F(g, 1)
> > > > >
> > >
> > > Gabor,
> > >
> > > There may be a better way of doing this and/or this will spark some
> > > thoughts.
> > >
> > > Let's create two simple functions:
> > >
> > >  f.inv <- function(x) {invisible(x)}
> > >
> > >  f <- function(x) {x}
> > >
> > > So we now have:
> > >
> > > > f.inv(1)
> > > > f(1)
> > > [1] 1
> > >
> > >
> > > > any(grep("invisible", (deparse(f))))
> > > [1] FALSE
> > >
> > > > any(grep("invisible", (deparse(f.inv))))
> > > [1] TRUE
> >
> > That's not going to work, since invisibility can also be a side effect
> > of assignment, e.g.
> >
> > g <- function(x) { x <- x }
>
> Good point.  Can we tweak it a bit to try to cover additional
> situations, such as this? For example:
>
>
> is.invisible <- function(x)
> {
>  dep.x <- deparse(x)
>
>  ifelse(any(grep("invisible", dep.x)) |
>         any(grep("<-", dep.x[length(dep.x) - 1])),
>         TRUE, FALSE)
> }
>
>
> f.inv <- function(x) {invisible(x)}
> f <- function(x) {x}
> g <- function(x) { x <- x }
>
>
> > is.invisible(f.inv)
> [1] TRUE
>
> > is.invisible(f)
> [1] FALSE
>
> > is.invisible(g)
> [1] TRUE
>
>
> In this case to (possibly) cover the assignment situation, I am looking
> for an assignment operator ("<-") in the last code line of the function
> body. Note that if there are blank lines in the function body after the
> assignment line and before the closing brace, the assignment line is
> still the final line of code found in the deparse().
>
> Given Duncan's comment, it sounds like this might not be doable for 100%
> of the situations, but we may be able to cover the 80% of the common
> ones.
>
> Gabor, to your follow up comment about generics, perhaps the code can be
> yet further extended to check the class of the relevant argument(s) to
> the function(s) in question to similarly search/deparse the methods that
> would presumably be dispatched. It would certainly become more
> convoluted however.

In the case of S3 one could search for a UseMethod and, if found, just
search all available methods for invisible without trying to figure out
which one(s) get dispatched on the theory that its likely
that they will all return or all not return invisibly since methods are
supposed to maintain a certain sense of semantic consistency.

In the case of internal R functions there may not be that many that
return invisibly so one could just make a list of them and check against
that list.  Is there some way to grep these out?




[Rd] how to determine if a function's result is invisible
Gabor Grothendieck