Carl Witthoft
Carl Witthoft

Reputation: 21532

function in loaded package doesn't appear in search path

I have a published package cgwtools which includes an overload of the ! operator. Here's the code from the source file splatnd.r :

`!` <- function (e1, e2) 
{
    call <- match.call()
    original <- function() {
        call[[1]] <- quote(base::`!`)
        return(eval(call, parent.frame(2)))
    }

    
    switch(paste(as.character(call[[2]]), sep = "", collapse = ""), 
        newdev = dev.new(width = 4.5, height = 4.5, restoreConsole = T), 
        qapla = cat("batlh tIn chav\n"), return(original()))
}

This is based on the neat tool in the sos package called ??? . If I simply source the ! code, it runs as expected. In the past, at least prior to R 3.2.x , loading the package cgwtools let me run ! as expected. I recently set up both versions 3.2.4 and 3.3.1 on a Windows 7 machine, and got an odd apparent failure to load. Here's some console text, showing the searchpath before and after loading cgwtools

> getAnywhere(`!`)
A single object matching ‘!’ was found
It was found in the following places
  package:base
  namespace:base
with value

function (x)  .Primitive("!")
> library(cgwtools)
> getAnywhere(`!`)
2 differing objects matching ‘!’ were found
in the following places
  package:base
  namespace:cgwtools
  namespace:base

By way of comparison, doing the same with the sos package returns what I'd expect:

> getAnywhere(`?`)
2 differing objects matching ‘?’ were found
in the following places
  package:sos
  package:utils
  namespace:utils
  namespace:sos

If I access the output, the correct source code is shown:

> getAnywhere(`!`)[2]
function (e1, e2) 
{
    call <- match.call()
    original <- function() {
        call[[1]] <- quote(base::`!`)
        return(eval(call, parent.frame(2)))
    }
    switch(paste(as.character(call[[2]]), sep = "", collapse = ""), 
        newdev = dev.new(width = 4.5, height = 4.5, restoreConsole = T), 
        qapla = cat("batlh tIn chav\n"), return(original()))
}
<environment: namespace:cgwtools>

But , as indicated by the lack of the text package:cgwtools , when I try to run, say !qapla from the gui console, I get the error message that qapla is not found, i.e. the .Primitive operator ! was invoked.

So the question is: why is the ! function in the cgwtools package not being recognized after loading the package? Did I do something dumb when building the package source, or did I find some bug in the CRAN builder?

Sub-question: I can't figure out any variant of the directed command cgwtools::'!'qapla that doesn't cause a parse error.

edit

In response to alexis_laz 's query:

> search()
 [1] ".GlobalEnv"        "package:cgwtools"  "package:stats"    
 [4] "package:graphics"  "package:datasets"  "package:grDevices"
 [7] "package:lattice"   "package:sos"       "package:brew"     
[10] "package:utils"     "package:methods"   "Autoloads"        
[13] "package:base" 

> cgwtools:::'!'qapla
Error: unexpected symbol in "cgwtools:::'!'qapla"

And,

> get('!')(qapla)
Error: object 'qapla' not found
> get('!',2)(qapla)
Error: object 'qapla' not found

Suggesting again that "!" didn't get exported from cgwtools . Note also that -- see above for the items returned from

 getAnywhere(`!`)

I can pull the code:

> getAnywhere(`!`)[2](qapla)
batlh tIn chav

Upvotes: 2

Views: 297

Answers (1)

Carl Witthoft
Carl Witthoft

Reputation: 21532

With thanks to @alexis_laz for his suggestions, I went back and looked at the default NAMESPACE file that package.skeleton generates. The file contains the line
exportPattern("^[[:alpha:]]+")

Clearly I need to add an explicit export('!') line to this file. (Plus the new requirements for explicit import of base packages per recent CRAN requirements,but that's a separate issue)

edit

For the inexperienced (like me), be aware that, after changing the NAMESPACE file, one must rebuild the package. Editing said file is insufficient.

Upvotes: 3

Related Questions