On 10/07/2017 3:37 PM, Schlaepfer, Daniel wrote:
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.

No, it is working just as documented.


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"

person and utils::person are both expressions that give a function as the value. "person" and "utils::person" are both expressions that give a character string, but "utils::person" is not the name of a function.

It's similar to this:

as.numeric(1)
as.numeric("1")
as.numeric(0+1)
as.numeric("0+1")

The 4th expression is not something that as.numeric knows how to coerce to a number. The rest are expressions that evaluate to 1 or "1", and as.numeric() knows how to deal with both of those.


Duncan Murdoch


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

______________________________________________
R-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel


______________________________________________
R-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel

Reply via email to