tidyverse/purrr

map as rerun replacement has weird behavior?

lmiratrix opened this issue · 4 comments

I believe the following code should print out "res" four times under the first map call below (it does) and also the second (it doesn't). Somehow the indices 1:reps in the map call are getting passed to the ~ one_run() syntax, and that is getting picked up by the 'data_only' variable, and I am not sure why (on my system)?

library( tidyverse )

one_run = function( one_sided = TRUE,
                    scaled_C = NULL,
                    perfect_X = FALSE, 
                    shuffle = FALSE,
                    data_only = FALSE, ...  ) {
    
    if ( data_only ) {
        return( paste0( "dta-", data_only ) )
    } else {
        return( "res" )
    }
}


run_sim <- function( reps, 
                     one_sided = TRUE,
                     scaled_C = NULL,
                     perfect_X = FALSE,
                     shuffle = FALSE, ... ) {
    runs <- 
        purrr::map( 1:reps, ~ one_run( one_sided = one_sided,
                                       scaled_C = scaled_C,
                                       perfect_X = perfect_X,
                                       shuffle = shuffle,
                                       ... ) ) 
    
    return( unlist( runs ) )
}



unlist( purrr::map( 1:4, ~ one_run() ) )

run_sim( reps = 4 )

Session info
R version 4.3.2 (2023-10-31)
Platform: aarch64-apple-darwin20 (64-bit)
Running under: macOS Sonoma 14.2.1

Matrix products: default
BLAS:   /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libBLAS.dylib 
LAPACK: /Library/Frameworks/R.framework/Versions/4.3-arm64/Resources/lib/libRlapack.dylib;  LAPACK version 3.11.0

locale:
[1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8

time zone: America/New_York
tzcode source: internal

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
 [1] lubridate_1.9.3 forcats_1.0.0   stringr_1.5.1   dplyr_1.1.4     purrr_1.0.2     readr_2.1.5    
 [7] tidyr_1.3.1     tibble_3.2.1    ggplot2_3.4.4   tidyverse_2.0.0

loaded via a namespace (and not attached):
 [1] vctrs_0.6.5       cli_3.6.2         rlang_1.1.3       stringi_1.8.3     pkgload_1.3.4    
 [6] generics_0.1.3    glue_1.7.0        colorspace_2.1-0  hms_1.1.3         scales_1.3.0     
[11] fansi_1.0.6       grid_4.3.2        munsell_0.5.0     tzdb_0.4.0        lifecycle_1.0.4  
[16] compiler_4.3.2    timechange_0.2.0  pkgconfig_2.0.3   rstudioapi_0.15.0 R6_2.5.1         
[21] tidyselect_1.2.0  utf8_1.2.4        pillar_1.9.0      magrittr_2.0.3    tools_4.3.2      
[26] withr_3.0.0       gtable_0.3.4  

Could you please provide a simpler example that illustrates the problem? (Maybe just be deleting all the arguments that argument actually used?)

Ok, how about this:

library( tidyverse )

one_run = function( a_flag = FALSE, ...  ) {
    
    if ( a_flag ) {
        return( paste0( "dta-", a_flag ) )
    } else {
        return( "res" )
    }
}

run_sim <- function( reps, ... ) {
    purrr::map_chr( 1:reps, ~ one_run( ... ) ) 
}

purrr::map_chr( 1:4, ~ one_run() )

run_sim( reps = 4 )

run_sim( reps = 4, a_flag = FALSE )

It looks like the "..." in the one_run() is getting mapped to the anonymous function's initial argument, which is the counter from map?

I think you're running into the complexities of the ~ helper. Life gets easier if you switch to the new base R anonymous function shorthand:

library(purrr)

one_run <- function(a_flag = FALSE, ...) {
    if (a_flag ) {
      paste0("dta-", a_flag)
    } else {
      "res"
    }
}

run_sim <- function( reps, ... ) {
  purrr::map_chr(1:reps, \(i) one_run( ... )) 
}

run_sim(reps = 4, a_flag = TRUE)
#> [1] "dta-TRUE" "dta-TRUE" "dta-TRUE" "dta-TRUE"
run_sim(reps = 4, a_flag = FALSE)
#> [1] "res" "res" "res" "res"

Created on 2024-07-23 with reprex v2.1.0

Ok, so the "~" method has some weirdness; I will try and update my coding habits to (i). I like the explicitness of the parameter, at least. :-)