[Rd] operator :: and symbols not in the namespace of a package with a namespace (PR#9279)

Duncan Murdoch murdoch at stats.uwo.ca
Fri Oct 6 16:59:32 CEST 2006


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
>>
>




More information about the R-devel mailing list