r-lib / callr

Call R from R
https://callr.r-lib.org/
Other
299 stars 38 forks source link

How Do I Pass A Custom Function To callr::r()? #260

Closed drag05 closed 1 year ago

drag05 commented 1 year ago

I have been successful passing functions from other packages to r(). However, I have problems passing a custom function i.e. a function defined inside the global env.

I have tried this and got NULL:

> dt = myData
>  x = 'other argument'
> myCustomFun = function(dt, x,  ...) { <code here> }

> result = callr::r(
                       function(myCustomFun, dt, x) {
                                                rez = myCustomFun( dt, x)
                             return(rez)
                        }
            , args = list(myCustomFun, dt, x)
)

> result
NULL

I assume add_hook() may be the way. However the documentation lacks detail. Please advise, thank you.

gaborcsardi commented 1 year ago

Yeah, that actually works for me. Can you show a real example that fails for you? With code that we can run?

drag05 commented 1 year ago

@gaborcsardi Here is a short example with explanations which does not contain a custom function:

ldt1 is a component of ldt list of data.table class data frames nme1 is one of ldt names

> ldt1 = ldt[[1L]][, 'Modification' := NULL]
> nme1 = names(ldt)[1L]

> tb1 = callr::r(function(ldt1, nme1) {

         p = pander::pander(data.table::setDF(ldt1) , caption = paste0('Modification: ', nme1)) 
         return(p)

         }, args = list(ldt1, nme1)
)

tb1
> NULL

where: ldt1 = Site %Area S1 %Area S2 1: K63 0.00 0.00 2: K69 0.00 0.00 3: K76 4.41 1.42 and nme1 = "Acetyl"

There are as many tables (and as many plots) as length(ldt). My intention is to create all in parallel and then collect them in a Report. If this works, I would wrap everything in other custom functions of the form:

makeTab/makePlot =  function(x, y, ...) {

          tb = callr::r(function(x, y) { <similar code as above> }, args = list(x, y))
          return(tb)
}

or, one custom function with a switch for table or plot. Thank you!

gaborcsardi commented 1 year ago

I am sorry, but this is not something I can run. See e.g. https://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example on creating a reproducible example.

drag05 commented 1 year ago

@gaborcsardi This should work

require(data.table)
 ldt1 = as.data.table(iris)
 nme1 = 'Iris'

  tb1 = callr::r(function(ldt1, nme1) {
         p = pander::pander(data.table::setDF(ldt1), caption = paste0('Modification: ', nme1))
            return(p)
         }, args = list(ldt1, nme1)
   )

 tb1
gaborcsardi commented 1 year ago

Yes, tb1 is NULL, that's what pander::pander() returns.

drag05 commented 1 year ago

@gaborcsardi Actually, no:

require(data.table)
ldt1 = as.data.table(iris)
nme1 = 'Iris'

  tb1 = pander::pander(data.table::setDF(ldt1), caption = paste0('Modification: ', nme1))

tb1

----------------------------------------------------------------------
 Sepal.Length   Sepal.Width   Petal.Length   Petal.Width    Species   
-------------- ------------- -------------- ------------- ------------
     5.1            3.5           1.4            0.2         setosa   

     4.9             3            1.4            0.2         setosa   

     4.7            3.2           1.3            0.2         setosa   
...
Table: Modification: Iris
gaborcsardi commented 1 year ago

Acrtually, yes. pander() prints the table to the screen and then returns NULL:

❯ tb1
NULL
drag05 commented 1 year ago

@gaborcsardi The table is not printed anywhere. Just the NULL result. Any way, please post a reproducible example. Thank you!

gaborcsardi commented 1 year ago

Yes, the subprocess cannot print to the screen. That is as expected, e.g. here is a simple example:

callr::r(function() { print("hi there"); message("again") })
#> NULL

If you want to return the output, then you need to capture it or write it to a file: https://github.com/r-lib/callr#standard-output-and-error

drag05 commented 1 year ago

@gaborcsardi OK! With stdout not NULL and show = TRUE the table is printed to the Report. Thank you!