From J.C.Rougier@durham.ac.uk  Tue May  7 10:07:49 2002
From: J.C.Rougier@durham.ac.uk (Jonathan Rougier)
Date: Tue, 07 May 2002 10:07:49 +0100
Subject: [Rd] Behaviour of environment(foo)<- (PR#1509)
References: <200205031012.MAA13485@pubhealth.ku.dk> <x26625y1al.fsf@blueberry.kubism.ku.dk> <3CD26B35.1F72FD86@durham.ac.uk> <20020503092633.A11402@nokomis.stat.umn.edu>
Message-ID: <3CD79965.F38D93F1@durham.ac.uk>

Luke Tierney wrote:
> 
> A similar warning would be appropriate for formals<- and body<-.  When
> you define a function the usual way you cause a function expression
> consisting of formals and body to be evaluated in a particular
> environment.  That creates a closure in which the three pieces are
> assembled in a consistent fashion.  Assigning to any one of them
> separately is quite likely to lead to inconsistencies and is one
> reason the internal code loses all attributes on the function when you
> do this (in particular the 'source' attribute if there was one).  If
> we get byte code compilation and f is a compiled function, then after
> 
>         environment(f)<- myenv
> 
> the value of f will have to either be an interpreted function or the
> assignment will have to trigger a new compilation since the original
> compilation will have used information from the original environment.
> 
> In fact, given these issues I would argue that a pretty strong case
> can be made for eliminating formals<-, body<- and environment<- (at
> least for functions), though there are some very limited circumstances
> where they can be useful if used with care.
> 
> So, after all that, the real question: why are you doing this and are
> you sure there isn't a better way?

Now you've scared me!  I've been using the "list of functions with a
common environment" approach to implement objects with methods and
shared data, similar to that used by Douglas Bates and Saikat DebRoy in
"nls", particularly their function "nlsModel".  So I can write
foo$method() to use method on the foo object and its collection of
common variables.  If I want to assign a function defined outside as a
method then I need something like

robj$method <- functionDefinedOutside
environment(robj$method) <- myEnv

inside the function that constructs foo by returning the list robj. 
This enables functionDefinedOutside to reference variables in foo
directly, which makes for much clearer code.  The problem for me arose
when I was debugging a new method.  Rather than rebuilding object foo
from scratch each time I make a change in functionDefinedOutside I find
it easier just leave functionDefinedOutside on its own in the package
and use

environment(functionDefinedOutside) <- foo$getEnv()

(where the getEnv method simply returns myEnv) to simulate it being a
method of foo, and then I can test it where it stands.

I like the foo$method() construction: I find it easy to work with and
think it is quite transparent.  Is it likely to stop working in a future
version of R?  
And are there current risks I have yet to encounter?

Cheers, Jonathan.

-- 
Jonathan Rougier                       Science Laboratories
Department of Mathematical Sciences    South Road
University of Durham                   Durham DH1 3LE
tel: +44 (0)191 374 2361, fax: +44 (0)191 374 7388
http://www.maths.dur.ac.uk/stats/people/jcr/jcr.html
-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-
r-devel mailing list -- Read http://www.ci.tuwien.ac.at/~hornik/R/R-FAQ.html
Send "info", "help", or "[un]subscribe"
(in the "body", not the subject !)  To: r-devel-request@stat.math.ethz.ch
_._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._


[Rd] Behaviour of environment(foo)<- (PR#1509)
Jonathan Rougier