[Rd] 'do.call' appears to show inconsistent behavior for arguments of format "pkg::fun"
Schlaepfer, Daniel
daniel.schlaepfer at yale.edu
Mon Jul 10 21:37:11 CEST 2017
Hi all,
I believe that 'do.call' shows inconsistent/undocumented behavior when its 'what' argument is of the format "pkg::fun". The documentation (?do.call) suggests that
what: either a function or a non-empty character string naming the function to be called.
Thus, I expected that all four of below formats of the value for the 'what' argument would work, here I use 'utils::person' as an example:
Three formats work:
> do.call(person, list(given = "Jane", family = "Doe"))
> do.call("person", list(given = "Jane", family = "Doe"))
> do.call(utils::person, list(given = "Jane", family = "Doe"))
but the format "pkg::fun" doesn't work as I expected:
> do.call("utils::person", list(given = "Jane", family = "Doe"))
Error in `utils::person`(given = "Jane", family = "Doe") :
could not find function "utils::person"
This seemingly inconsistent behavior of 'do.call' is also exposed when working in parallel and the message doesn't make it easy to see that this error derives actually from 'do.call'.
> library(parallel)
> cl <- makePSOCKcluster(2)
These work
> clusterCall(cl, person, list(given = "Jane", family = "Doe"))
> clusterCall(cl, "person", list(given = "Jane", family = "Doe"))
> clusterCall(cl, utils::person, list(given = "Jane", family = "Doe"))
This doesn't work
> clusterCall(cl, "utils::person", list(given = "Jane", family = "Doe"))
Error in checkForRemoteErrors(lapply(cl, recvResult)) :
2 nodes produced errors; first error: could not find function "utils::person"
This is again not obvious from the documentation (?clusterCall): fun, FUN: function or character string naming a function.
This behavior of 'clusterCall' is because the function 'makePSOCKcluster' calls newPSOCKnode() which calls .slaveRSOCK(), which calls slaveLoop(). This is then waiting and on receving an appropriate message will call 'do.call':
> value <- tryCatch(do.call(msg$data$fun, msg$data$args, quote = TRUE), error = handler)
Thus, if 'msg$data$fun' (as received from recvData() which was sent via sendData(), via postNote() from function sendCall() wrapped in clusterCall()) is of the type "pkg::fun", then this will fail as above and work otherwise.
## Temporary work-around: re-define function in local namespace and export to workers
> temp_fun <- function(...) utils::person(...)
> clusterExport(cl, "temp_fun")
> clusterCall(cl, "temp_fun", list(given = "Jane", family = "Doe"))
Clean up
> stopCluster(cl)
## Motivation: I learned about this behavior of 'do.call' when attempting to write code such as
> Rmpi::mpi.bcast.cmd(mypackage2::fun, ...)
in my package1. The function Rmpi::mpi.bcast.cmd() calls eventually something along the lines of
> scmd <- scmd <- substitute(cmd)
> arg <- list(...)
> scmd.arg <-serialize(list(scmd=scmd, arg=arg), NULL)
> if (length(scmd.arg$args) > 0)
> do.call(as.character(scmd.arg$$scmd), scmd.arg$args, envir = .GlobalEnv)
and thus expresses this same inconsistent behavior of do.call. I cannot avoid calling with pkg::fun because a package should not attach another package and change the search path of the user.
## My installation
> sessionInfo()
R version 3.4.1 (2017-06-30)
Platform: x86_64-apple-darwin16.6.0 (64-bit)
Running under: macOS Sierra 10.12.5
Matrix products: default
BLAS: /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libBLAS.dylib
LAPACK: /opt/local/Library/Frameworks/R.framework/Versions/3.4/Resources/lib/libRlapack.dylib
locale:
[1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8
attached base packages:
[1] stats graphics grDevices utils datasets methods base
loaded via a namespace (and not attached):
[1] compiler_3.4.1
I would appreciate any help with identifying whether this is indeed inconsistent/undocumented behavior of 'do.call' or whether I am simply missing the point and how to deal with the situation.
Thank you,
Daniel Schlaepfer
More information about the R-devel
mailing list