From Mark.Bravington at csiro.au  Sun Apr  6 17:32:40 2003
From: Mark.Bravington at csiro.au (Mark.Bravington@csiro.au)
Date: Sun Apr  6 08:33:07 2003
Subject: [Rd] namespaces and assignment: a problem/question
Message-ID: <A8877251964B294BAB5BA1FC58B43FED025B45B3@molly.tas.csiro.au>

This is a question about namespaces and assignment. It's occasioned because
one of my functions stopped working at about R1.6 with the arrival of
'namespace:base', and I'm anxious to find out what will happen when 1.7
arrives. But the question might be of more general relevance (hence my
desire to get it in before "lockdown" on 9th April).

I have a function 'mtrace' which is supposed to overwrite the "most
findable" instance of its argument. 'mtrace' could be called either from the
command line, or from inside another function (i.e. somewhere in a stack of
temporary frames). Conceptually, what 'mtrace' does is:

mtrace( fname) {
  # fname is a character string that is a function name
  old.version <- get( fname, inherits=TRUE)
  new.version <- some.modification.of( old.version)
  
  # Overwrite old.version with new.version
  do.call( '<<-', fname, new.version)
}

The 'do.call( "<<-"...)' always used to overwrite into the environment where
'fname' originally lived, regardless of whether this was a frame in the set
of enclosures of the frame where 'mtrace' was called, or in the search path
of permanent workspaces. In particular, this ensured that the next time
'fname' was invoked (from the same frame as 'mtrace', or from a descendant),
the modified version would be called.

Since R1.6.?, though, this hasn't worked for functions defined in
'package:base'. Although it's possible to explicitly overwrite things in
'base' using 'assign', '<<-' no longer works (it creates a copy in
'.GlobalEnv' instead). Unfortunately, I can't use 'assign' directly, because
if 'fname' actually lives in an enclosing frame rather than a permanent
workspace, there is no way to figure out which enclosing frame, and thus
where to assign 'fname' to. [I recall reading somewhere about "there is no
way to identify the enclosing environment of a given environment".]

My current hack is to check whether the environment of 'fname' is
'.BaseNamespaceEnv', and if so to use 'assign( envir=' rather than '<<-'.
However, this isn't really satisfactory, as it's possible for a function to
have environment '.BaseNamespaceEnv' but not to reside in 'package:base'. I
also have no idea whether this sort of thing would work at all when 1.7.0
arrives.

One way around all this, might be to have an analog of 'find' that looks
through temporary enclosures before peeking into the search path. [?Also
some extension of 'find' that could take a package as a starting point, then
look through namespace imports? Here I am well out of my depth]  Then I
could just use 'superfind' followed by 'assign'. Is this a meaningful idea?
Could it be implemented simply? (Presumably yes, by just mirroring the way R
searches for objects..?)

It seems to me as though there might be a logical gap hereabouts with
assignment. I've had a bit of a look in the new "A simple implementation of
name spaces for R", and it seems that the section on "Sealing" is relevant--
e.g. are values being sealed rather than bindings? But I don't want to
inadvertently give any misleading impression that I actually understand how
namespaces will work! There are some complexities here (for me anyway), so
I'd much appreciate any guidance

Mark

*******************************

Mark Bravington
CSIRO (CMIS)
PO Box 1538
Castray Esplanade
Hobart
TAS 7001

phone (61) 3 6232 5118
fax (61) 3 6232 5012
Mark.Bravington@csiro.au


[Rd] namespaces and assignment: a problem/question
Mark.Bravington@csiro.au