Search code examples
rdata.tabledevtoolsroxygen2

Why does using "<<-" in a function in the global workspace work, but not in a package?


I'm creating a package using devtools and roxygen2 (in RStudio), however after I've built the package my function no longer works as intended. Yet, if I load the function's .R file and run the function from there in RStudio, it works perfectly. I've created another package using this method before and it worked fine (13 functions all working as intended from my other package), yet I cant seem to get this new one to work.

To start creating the package I start with:

library("devtools")
devtools::install_github("klutometis/roxygen")
library(roxygen2)
setwd("my parent directory")
create("triale")

All is working fine so far. So I put my .R file containing my function in the R folder under the triale folder. The .R file looks like this:

#' Trial Z Function
#'
#' This function counts the values in the columns
#' @param x is the number
#' @keywords x
#' @export
#' @examples
#' trialz()

trialz = function(x) {w_id= c(25,x,25,25,25,1,1,1,1,1);
wcenter= c(rep("BYSTAR-1",10)); 
df1 <<- data.frame(w_id, wcenter);
countit <<- data.table(df1); 
view <<- countit[, .N, by = list(w_id, wcenter)]; 
View(view)}

Again if I were to just run the code from the .R file, and test the function it works fine. But to continue, next I enter:

setwd("./triale")
document()

The triale documentation is updated, triale is loaded, and the NAMESPACE and trialz.Rd are both written so that trialz.Rd is under the man folder, and NAMESPACE is under the triale folder as intended. Next I install triale:

setwd("..")
install("triale")

Which I know works because I get the following:

Installing triale
"C:/PROGRA~1/R/R-31~1.3/bin/x64/R" --vanilla CMD INSTALL  \
  "C:/Users/grice/Documents/R/triale"  \
  --library="C:/Users/grice/Documents/R/win-library/3.1" --install-tests 

* installing *source* package 'triale' ...
** R
** preparing package for lazy loading
** help
*** installing help indices
** building package indices
** testing if installed package can be loaded
*** arch - i386
*** arch - x64
* DONE (triale)
Reloading installed triale

Package is now built, so I do the following:

library("triale")
library("data.table")

Note whenever I load the package data.table I get the following error message:

data.table 1.9.4  For help type: ?data.table
*** NB: by=.EACHI is now explicit. See README to restore previous behaviour.

However it doesnt seem to affect my function. So now its time to test my function from my package:

trialz(25)

This goes through, and I of course get a populated df1, and countit, but for whatever reason view is always empty (as in 0 obs. of 0 variables).

So I test my work using the dummy code below:

>trialy = function(x) {wid= c(25,x,25,25,25,1,1,1,1,1);
                  wc= c(rep("BYSTAR-1",10)); 
                  df2 <<- data.frame(wid, wc);
                  countitt <<- data.table(df2); 
                  viewer <<- countitt[, .N, by = list(wid, wc)]; 
                  View(viewer)}

>trialy(25)

Even though this is the same exact code with just the names changed around it works. Dumbfounded I open trialz.R and copy the function from there and run it as below, and that works:

> trialz = function(x) {w_id= c(25,x,25,25,25,1,1,1,1,1);
 wcenter= c(rep("BYSTAR-1",10));
 df1 <<- data.frame(w_id, wcenter);
 countit <<- data.table(df1); 
view <<- countit[, .N, by = list(w_id, wcenter)];
View(view)}
> trialz(25)

Since I've created a package before I know my method is solid (that package had 13 dif. functions, all of which worked). I just don't understand how a function can work fine as written, yet when I package it, the function no longer works. Again here is where it stops working as intended when using my package:

view <<- countit[, .N, by = list(w_id, wcenter)];
View(view)}

And my end result should look something like this, if my package worked:

    wid wc          N
1   25  BYSTAR-1    5
2   1   BYSTAR-1    5

Can anyone explain why view is never populated after I package my function? I've tested it as much as I know how, and my results should be reproducible for anyone thats willing to try it for themselves. Thanks, I appreciate any feedback.


Solution

  • Your problem here is that "<<-" does not create variables in the global environment but rather in the parent environment. (See help("<<-").)

    The parent environment of a function is the environment in which it has been defined. In the case where you defined your function directly in your workspace, this parent environment actually is the same as your workspace environment (namely: .GlobalEnv), which is why your variables are assigned values as you expect them to. In the case where your function is packaged, however, the parent environment is the package environment and not the .GlobalEnv! This is why you do not see your variables being assigned values in your workspace.

    Refer to the chapter on environments in Hadley's book and How R Searches and Finds Stuff for more details on environments in R.

    Note that doing this would not be considered a proper debugging technique, to say the least. In general, you never want to use the "<<-" operator.

    For options on debugging R code, see, e.g., this question. I, in particular, like the debugonce function very well. See ?debugonce.