3
votes

Is there a way to use the arguments passed to the original function in the otherwise argument of purrr::possibly()?

For example (this is a dumb toy example--the real code involves web scraping behind a password-protected portal):

library(tidyverse)
library(purrr)

foo  <- tibble(x = 1:3, y = 1:3)

toyfunction  <- function(x, df = foo) {
   df[x, x] %>%
     mutate(indexed_at = x)
}

# gives an error once we get over 3
map(1:6, toyfunction)

# so, let's make it safe
possiblyversion  <- possibly(toyfunction, otherwise = 12345) 

# this works, but get confusing & inconsistent (I couldn't use map_dfr() if I wanted to!)
map(1:6, possiblyversion)

# ideally, something like this would be possible
idealpossible  <- possibly(
     toyfunction(x, df = foo)
   , otherwise = tibble(x = NA, y = NA, indexed_at = x)
)

# so we get results like this:
idealpossible(6)

# A tibble: 1 x 2
      x          y    indexed_at
  <int>      <int>         <dbl>
     NA         NA            6

Keeping the job running and returning consistent results are higher priorities than capturing the errors and whatnot, which is why I haven't considered safely() or quietly().

Is there any way to use the original function arguments in the otherwise results?

1

1 Answers

2
votes

Since safely() and possibly() only allow a static value for otherwise=, you would need to write your own wrapper. Here's a crude example of what this might look like

possibly2 <- function(.f, otherwise=NULL) {
  function(...) {
    tryCatch({
      .f(...)  
    }, error = function(e) otherwise(...))
  }
}

wrapped_toy <- possibly2(
  toyfunction, 
  function(x, df) tibble(x = NA, y = NA, indexed_at = {{x}})
)
map_dfr(1:6, wrapped_toy)

This doesn't do any real error checking but basically you can pass in a function to otherwise() that will get called with the same parameters as the base function.