7.6 Safely dealing with failure

safely is a function that takes a function, and returns a modified version of that function. Like how decorators work in Python.

safe_log <- safely(log)
safe_log(10)
## $result
## [1] 2.302585
## 
## $error
## NULL
safe_log("a")
## $result
## NULL
## 
## $error
## <simpleError in .Primitive("log")(x, base): non-numeric argument to mathematical function>
x <- list(1, 10, "a")
y <- x %>% map(safely(log))
str(y)
## List of 3
##  $ :List of 2
##   ..$ result: num 0
##   ..$ error : NULL
##  $ :List of 2
##   ..$ result: num 2.3
##   ..$ error : NULL
##  $ :List of 2
##   ..$ result: NULL
##   ..$ error :List of 2
##   .. ..$ message: chr "non-numeric argument to mathematical function"
##   .. ..$ call   : language .Primitive("log")(x, base)
##   .. ..- attr(*, "class")= chr [1:3] "simpleError" "error" "condition"

You can specify the error value

safe_log <- safely(log, otherwise = NA)
x <- list(1, 10, "a")
y <- x %>% map(safe_log)

Extract values out manually

y %>% purrr::map_dbl(magrittr::extract(1))
## [1] 0.000000 2.302585       NA

Use the transpose function

y <- y %>% purrr::transpose()
str(y)
## List of 2
##  $ result:List of 3
##   ..$ : num 0
##   ..$ : num 2.3
##   ..$ : logi NA
##  $ error :List of 3
##   ..$ : NULL
##   ..$ : NULL
##   ..$ :List of 2
##   .. ..$ message: chr "non-numeric argument to mathematical function"
##   .. ..$ call   : language .Primitive("log")(x, base)
##   .. ..- attr(*, "class")= chr [1:3] "simpleError" "error" "condition"
y$result %>% purrr::flatten_dbl()
## [1] 0.000000 2.302585       NA