Mark.Bravington@csiro.au
2003-Apr-06 08:33 UTC
[Rd] namespaces and assignment: a problem/question
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