From luke at stat.uiowa.edu  Sun Oct 29 15:02:48 2006
From: luke at stat.uiowa.edu (Luke Tierney)
Date: Sun, 29 Oct 2006 08:02:48 -0600 (CST)
Subject: [Rd] how to determine if a function's result is invisible
In-Reply-To: <971536df0610290528x82176ay1744f059b26b13eb@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>
	<45438F9B.7000905@stats.uwo.ca> <4543D3A6.7010900@sciviews.org>
	<4543FB75.7090405@stats.uwo.ca>
	<971536df0610290503m9e653caoe0b14b077319d4cc@mail.gmail.com>
	<4544AB23.6070004@stats.uwo.ca>
	<971536df0610290528x82176ay1744f059b26b13eb@mail.gmail.com>
Message-ID: <Pine.LNX.4.64.0610290738080.23717@itasca2.wildberry.org>

On Sun, 29 Oct 2006, Gabor Grothendieck wrote:

> On 10/29/06, Duncan Murdoch <murdoch at stats.uwo.ca> wrote:
>> On 10/29/2006 8:03 AM, Gabor Grothendieck wrote:
>>> On 10/28/06, Duncan Murdoch <murdoch at stats.uwo.ca> wrote:
>>>> On 10/28/2006 6:03 PM, Philippe Grosjean wrote:
>>>>> Duncan Murdoch wrote:
>>>>> [...]
>>>>>> 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
>>>>> Excellent, many thanks... but I am afraid I cannot use this function
>>>>> because you force evaluation on parent.frame(), where I need to evaluate
>>>>> it in .GlobalEnv (which is NOT equal to parent.frame() in my context).
>>>>> Would it be possible to change it to:
>>>>>
>>>>> withVisible <- function(x, env = parent.frame()) {
>>>>>      x <- substitute(x)
>>>>>      v <- .Internal(eval.with.vis(x, env, baseenv()))
>>>>>      v
>>>>> }
>>>>>
>>>>> ...so that we got additional flexibility?
>>>> As I said, that's not needed.  Use evalq(withVisible(x), envir=.GlobalEnv).
>>>
>>> Even if its not strictly necessary in terms of minimality it still might be
>>> convenient and consistent with other eval-style functions which do tend
>>> to provide an env= or in the case of lm-style functions a data= argument.
>>> Also its very easy to do and the underlying internal function supports it.
>>
>> I agree with Luke here.  It's a bad design to make every function do
>> everything.  This function reveals the "R_visible" flag.  It doesn't
>> need to do anything else.
>>
>> Duncan Murdoch
>>
>
> But I think that consistency with the rest of R is more important here.
> R is hardly minimal -- its a grab bag of a huge amount of functionality
> thrown in by numerous people working in parallel so I don't think that
> minimality is the right principle here.
>
> If one did not know the calling sequence I think a reasonable guess
> would be that there would be such an env= argument so the principle of least
> surprise suggests that it be there.

You are missing the point. withVisible is not an eval-type function in
the sense of taking a quoted expression as its argument and evaluating
that in a particular environment.  It instead insures that the literal
argument expresion is evaluated in a way consistent with standard
evaluation within a context where the visibility is captured.  As such
it is more closely related to try or tryCatch than to eval.  The
language we use to distinguish these cases in the documentation isn't
ideal and could use some work.

Use of nonstandard evaluation, i.e. direct calls to eval, are a source
of many bugs and confusions to code readers (people or code analysis
tools).  We need to avoid encouraging more of that. That is why it
makes sense to handle things such as this in a way that is consistent
with standard evaluation.  If you have an unevaluated expression you
want to evaluate in a way that captures the visibility then

     evalVis <- function(...) withVisible(eval(...))

will do this.

The current implementation does happen to use an eval construct but
that isn't guaranteed to remain. Conceptually what we want is
something that captures an argument promise and insures that this is
forced in a way that captures
visibility. .Internal(eval.with.vis(substitute(...))) happens to be a
convenient way to do this at the moment but should be changed
eventually to work in terms of promises (so that byte compiled
promises, for example, are run as byte compiled code, not by
interpreted as would happen now.)


Best,

luke

-- 
Luke Tierney
Chair, Statistics and Actuarial Science
Ralph E. Wareham Professor of Mathematical Sciences
University of Iowa                  Phone:             319-335-3386
Department of Statistics and        Fax:               319-335-3017
    Actuarial Science
241 Schaeffer Hall                  email:      luke at stat.uiowa.edu
Iowa City, IA 52242                 WWW:  http://www.stat.uiowa.edu




[Rd] how to determine if a function's result is invisible
Luke Tierney