operator :: and symbols not in the namespace of a package with a namespace (PR#9279)
On 10/6/2006 10:44 AM, Luke Tierney wrote:
On Fri, 6 Oct 2006, Duncan Murdoch wrote:
On 10/6/2006 9:05 AM, thomas.friedrichsmeier at rub.de wrote:
Full_Name: Thomas Friedrichsmeier
Version: 2.4.0
OS: GNU/Linux
Submission from: (NULL) (84.61.116.51)
Since R 2.4.0, operator "::" also returns objects in the package environment, if
the package does not have a namespace. This is a very welcome addition.
Additional wish:
If a package has a namespace, but does not place all symbols in that namespace,
lookup will still fail. For example in package boot (version 1.2-26):
library (boot)
exists ("motor", envir=as.environment ("package:boot")) # TRUE
getAnywhere ("motor") # found in
package:boot
boot::motor # error not in
namespace
This is as documented, but I think it would be convenient, if boot::motor would
also return the object in this case.
At first I was ready to disagree with you, telling you to use the ":::" operator for something that is not exported: but in fact motor is a dataset, so it is exported from the package by being loaded into the package environment when the package is loaded. I agree that the "::" operator should find it.
It might be a good idea to rethink the decision to have data be handled specially instead of having data sets be treated as ordinary exported variables. There may be a good reason for doing what we do now but I don't know what it is. If there really is a good reason to continue this then maybe we should think about this addition. It doesn't feel like the right thing to do but may be harmless.
I think there would be a good reason if it was expensive to load datasets, but now it's cheap, so I don't think there's a good reason any more.
I think the rule should be: the "::" operator looks at the symbols that
are publicly available from the package, i.e. boot::motor should
effectively be an abbreviation for
get("motor", pos="package:boot", inherits=FALSE)
after making sure boot is loaded. I think getExportedValue() is a much
more rarely needed function, so users should need to use it explicitly.
No. :: exists precisely to allow code to access exported variables without attaching the namespace. It is the only way I use this feature and the reason the feature exists.
Right, the description I gave above is wrong, but I think the current behaviour is wrong too. A reasonable alternative use for "::" is to specify where to go to look for a variable whose name may clash with another. Avoiding the side effect of changing the search list is a very nice feature of it. Is there a simple way to do a load of a package as if it was being attached, but without putting it into the search list? If so, that's what I meant above :-), with the search taking place in the public environment of the package. Duncan Murdoch
Best, luke
Duncan Murdoch
This might be achieved by adding an additional tryCatch in "::": If the package
has a namespace, try getExportedValue (), if that fails, try to get from package
environment instead. E.g.:
"::" <- function (pkg, name)
{
pkg <- as.character(substitute(pkg))
name <- as.character(substitute(name))
ns <- tryCatch(asNamespace(pkg), hasNoNamespaceError = function(e) NULL)
if (is.null(ns)) {
pos <- match(paste("package", pkg, sep = ":"), search(),
0)
if (pos == 0)
stop(gettextf(paste("package '%s' has no name space and",
"is not on the search path"), pkg), domain = NA)
get(name, pos = pos, inherits = FALSE)
}
else tryCatch(getExportedValue(pkg, name), error=function (e) {
pos <- match(paste("package", pkg, sep=":"), search(),
0)
get(name, pos, inherits=FALSE)
})
}
______________________________________________ R-devel at r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel
______________________________________________ R-devel at r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel