Skip to content

Increase transparency: suggestion on how to avoid namespaces and/or unnecessary overwrites of existing functions

6 messages · Duncan Murdoch, Dominick Samperi, Joshua Wiley +1 more

#
On 11-08-23 2:23 PM, Janko Thyson wrote:
I agree there can be a problem, but I don't think it is necessarily as 
serious as you suggest.  Even though there are more and more packages 
available, most people will still use roughly the same number of them. 
Just because CRAN has thousands of packages doesn't mean I use all of 
them at the same time.
If your code had been in a package with a NAMESPACE, it would not have 
been affected by a user loading forecast.  (If you start importing it, 
then of course it could cause masking problems.)

You suggest above that users only put code into a package very late in 
the development process.  The solution is, don't do that.  Create a 
package early on, and use it through the majority of development time.

You can leave the choice of exports until late by exporting everything; 
you'll still get the benefit of the more controlled name search from the 
beginning.

You say you can't use "namespace::call()" until the namespace package 
has been written.  But why would you want to?  If the call is coming 
from the new package, objects in it will be used with first priority in 
resolving the call.  You only need the :: notation when there are 
ambiguities in calls to external packages.
I think long names with consistent prefixes are harder to read than 
short descriptive names.  I think this would make code harder to read. 
For example, the first few lines of mean.default would change from

     if (!is.numeric(x) && !is.complex(x) && !is.logical(x)) {
         warning("argument is not numeric or logical: returning NA")
         return(NA_real_)
     }

to

     if (!base_is.numeric(x) && !base_is.complex(x) &&
	!base_is.logical(x)) {
         base_warning("argument is not numeric or logical: returning NA")
         return(base_NA_real_)
     }
That seems like good advice.

Duncan Murdoch
#
On Sat, Oct 1, 2011 at 1:08 PM, Duncan Murdoch <murdoch.duncan at gmail.com> wrote:
Except that namespace::foo should be assigned to another local
variable instead of using package::foo in a tight loop, because
repeated calls to "::" can introduce a significant performance
penalty. (This has been discussed in another thread.)
#
On 11-10-01 5:14 PM, Dominick Samperi wrote:
That's good advice too.

Duncan Murdoch
#
On Oct 1, 2011, at 6:14 PM, Duncan Murdoch wrote:

            
Well, if this idiom is used more often, we may re-consider the implementation of `::` - it could definitely be sped up if needed, but I think so far the view was that it's not worth the hassle (aka increased complexity and relative ugliness of making it a special form) ...

Cheers,
Simon
#
On Sat, Oct 1, 2011 at 3:14 PM, Duncan Murdoch <murdoch.duncan at gmail.com> wrote:
[snip]
Is this performance hit the sort of thing that byte compiling would
help with, or am I misunderstanding its use?
#
On Oct 1, 2011, at 7:52 PM, Joshua Wiley wrote:

            
Depending on what you mean ;). If you mean that compiling code containing :: removes the issue, yes, that is indeed true (i.e., foo::bar gets compiled into the actual value since the compiler can assume that it is a constant and thus :: is not actually called).

If you mean that compiling base and thus :: then that helps only to a degree. According to microbenchmark the overhead of :: is in the order of 7.5ms when compiled and 11ms when not compiled on my test machine (Xeon X5690 and R-devel which is actually much faster than the 30ms in R 2.13.1). If the time spent in your actual function is in the order of  microseconds then the overhead is still huge in either case. If it's much bigger then either doesn't matter.

Cheers,
Simon