Jim Maas
Jim Maas

Reputation: 1729

Can not change boolean variable value inside foreach function with doMPI

I've built the following mwe that shows a series of nested functions, that are called inside a foreach statement, with MPI as a backend. All of this is packaged inside an R package. The problem is that when I load the package, and then call fun3, I can not get it to change the value of fun3on from TRUE to FALSE. Any suggestions? The complete code is at https://github.com/jamaas/toymod3.git.

Expect that calling

fun1(fun3on = FALSE)

to change the output values, but it does not?

#' Test function level 1
#' @param var11 first variable for function 1
#' @param var12 second variable for function 1
#' @param var13 third variable for function 1
#' @export fun1

fun1 <- function (var11=10, var12=8, var13=5,
                  var21=0.05, var22=9.876,
                  fun3on=TRUE, ...) {

    results <- data.frame (foreach::`%dopar%`(
            foreach::`%:%`(foreach::foreach(j = 1:var11,
                                            .combine = cbind,
                                            .packages="toymod2",
                                            .export = "fun3on"),
            foreach::foreach (i = 1:var12, .combine=rbind)),
                   out3 <- replicate(var13, do.call(fun2, list(var21, var22)))
        )
)
## save outputs for subsequent analyses if required
saveRDS(results, file = paste("./outputs/", var13 ,"_", var12, "_", var11, "_",
                              format(Sys.time(), "%d_%m_%Y"), ".rds", sep=""))
return(results)
}

#' Test function level 2
#' @param var21 first variable for function 2
#' @param var22 second variable for function 2
#' @export fun2

fun2 <- function (var21=0.05, var22=9.876, ...) {
    out2 <- `if` (rpois(1, var21) > 0,
                    var22 * fun3(...),
                  0)
}

#' Test function level 3
#' @param var31 first variable for function 3
#' @param var32 second variable for function 3
#' @param var33 third variable for function 3
#' @param fun3on turn the formula on or off
#' @export fun3

fun3 <- function (var31=1.396, var32=14.387,
                  var33=3.219, fun3on = TRUE, ...) {
    out3 <- `if` (fun3on,
                  var31 * rnorm(1, mean=var32, sd= var33),
                  500)
}

Upvotes: 0

Views: 57

Answers (2)

F. Priv&#233;
F. Priv&#233;

Reputation: 11738

The problem is that you are not passing fun3on to fun2 so it won't be passed to fun3.

In do.call(fun2, list(var21, var22)), change it to be do.call(fun2, list(var21, var22, fun3on = fun3on, ...)). Make sure to pass them as named arguments (I added the dots because you seem to have some in fun3).

PS: don't name your returns unless you use evocative names.

Upvotes: 1

CPak
CPak

Reputation: 13591

Looks complicated. I'd post as a comment but since this potential answer is longer and represents an attempt at answering your question, here goes

My guess is your problem lies here

In fun1 you call fun2

fun2 <- function (var21=0.05, var22=9.876, ...) {
    out2 <- `if` (rpois(1, var21) > 0,
                    var22 * fun3(...),
                  0)
}

fun2 calls fun3(...) without passing arguments

fun3 <- function (var31=1.396, var32=14.387,
                  var33=3.219, fun3on = TRUE, ...) {
    out3 <- `if` (fun3on,
                  var31 * rnorm(1, mean=var32, sd= var33),
                  500)
}

But fun3on is default TRUE in fun3

Maybe if you change (...) to (fun3on=fun3on)

fun2 <- function (var21=0.05, var22=9.876, ...) {
    out2 <- `if` (rpois(1, var21) > 0,
                    var22 * fun3(fun3on=fun3on),
                  0)
}

it might work???

Upvotes: 0

Related Questions