From MSchwartz at mn.rr.com  Thu Oct 26 05:22:43 2006
From: MSchwartz at mn.rr.com (Marc Schwartz)
Date: Wed, 25 Oct 2006 22:22:43 -0500
Subject: [Rd] how to determine if a function's result is invisible
In-Reply-To: <eb555e660610251916g16502346mad5808724a0d9905@mail.gmail.com>
References: <971536df0610251714u451cf80fy80bf38cb2f130734@mail.gmail.com>
	<1161825632.4556.14.camel@localhost.localdomain>
	<eb555e660610251916g16502346mad5808724a0d9905@mail.gmail.com>
Message-ID: <1161832963.4556.25.camel@localhost.localdomain>

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.

Thoughts?

Marc




[Rd] how to determine if a function's result is invisible
Marc Schwartz