From murdoch at stats.uwo.ca  Sat Oct 28 19:12:59 2006
From: murdoch at stats.uwo.ca (Duncan Murdoch)
Date: Sat, 28 Oct 2006 13:12:59 -0400
Subject: [Rd] how to determine if a function's result is invisible
In-Reply-To: <971536df0610260226o55726354j8cbdfa5af07ae508@mail.gmail.com>
References: <971536df0610251714u451cf80fy80bf38cb2f130734@mail.gmail.com>	<454023EA.4020403@stats.uwo.ca>	<971536df0610252002s46ef72b2n32df3e180a49e990@mail.gmail.com>	<45403561.1000808@stats.uwo.ca>
	<971536df0610260226o55726354j8cbdfa5af07ae508@mail.gmail.com>
Message-ID: <45438F9B.7000905@stats.uwo.ca>

On 10/26/2006 5:26 AM, Gabor Grothendieck wrote:
> On 10/26/06, Duncan Murdoch <murdoch at stats.uwo.ca> wrote:
>> On 10/25/2006 11:02 PM, Gabor Grothendieck wrote:
>>> On 10/25/06, Duncan Murdoch <murdoch at stats.uwo.ca> wrote:
>>>> On 10/25/2006 8:14 PM, 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)
>>>> I don't think there's a way to do that.  Internally there's a global
>>>> flag called R_Visible; if it is set to zero, the value won't print.  But
>>>>  it gets reset to 1 very easily (e.g. by adding 1 to the result of an
>>>> invisible function), and it's not available in the API for you to write
>>>> C code to look at it.
>>>>
>>>> I think you'll just have to do require the user of your F to tell you
>>>> that they want the result to be invisible.
>>>>
>>>> Duncan Murdoch
>>>>
>>> Perhaps R_Visible be made available at the R level in the future.
>>> It would be helpful in situations where you are transforming a
>>> function but want to keep aspects of it such as whether the
>>> return result is invisible.
>> Actually, there is a way, but it's undocumented (i.e., use at your own
>> risk).  It's the eval.with.vis function.  This is an internal function
>> that is used within source() and capture.output(); you'll have to guess
>> from the usage there what the args are.   But here's an F that does
>> something close to what you want:
>>
>>  > fix(F)
>>  > f <- function() 1
>>  > g <- function() invisible(1)
>>  >
>>  > F <- function (expr)
>> + {
>> +     expr <- substitute(expr)
>> +     pf <- parent.frame()
>> +     tmp <- .Internal(eval.with.vis(expr, pf,
>> +         baseenv()))
>> +     tmp
>> + }
>>  > F(f())
>> $value
>> [1] 1
>>
>> $visible
>> [1] TRUE
>>
>>  > F(g())
>> $value
>> [1] 1
>>
>> $visible
>> [1] FALSE
>>
>>
> 
> 
> Perfect.  Thanks!!!!

I've just added this function to R-devel (to become 2.5.0 next spring):

withVisible <- function(x) {
     x <- substitute(x)
     v <- .Internal(eval.with.vis(x, parent.frame(), baseenv()))
     v
}

Luke Tierney suggested simplifying the interface (no need to duplicate 
the 3 parameter eval interface, you can just wrap this in evalq() if you 
need that flexibility); the name "with.vis" was suggested, but it looks 
like an S3 method for the with() generic, so I renamed it.

Duncan Murdoch




[Rd] how to determine if a function's result is invisible
Duncan Murdoch