30 NA handling
Improve our vectorized function to handle NAs and errors gracefully instead of unwrapping.
In the previous version of this we didn’t handle errors and we didn’t handle NAs. We can add some checks and match statements to do safe error handling.
There are different schools of thought here. Some people think that any error should cause the operation to fail. I believe that for vectorized operations, errors should be handled with grace. To me that means that we ignore them and return an NA.
In the previous example we used .unwrap(). I want us to improve that function with error handling.
Handling NAs and errors
- During the
.into_iter(), lets first check if theRstris an NA by using the.is_na()method- If it is
true, then we return aNULL. We can do this by usingRobj::from(()) ()is called the unit-type, a special type of nothingness in Rust (technically an empty tuple)
- If it is
- Otherwise we try to parse!
- Then when we parse, we match on the result. If an error, same thing with
Robj::from(()) - Otherwise we convert the result into an
Robjwith.into_robj()
A tip for multiple line expressions in an iterator: wrap it in a bracket!
Exercise
Improve url_parse() so that NAs and parse errors both become NULL instead of panicking.
- Check each element for NA with
.is_na()and return().into_robj()if so - Otherwise
matchonRUrl::new(xi)and return().into_robj()onErr - Collect into a
List
After devtools::document() and devtools::load_all(), test it with a vector that hits all three cases—a valid URL, an NA, and an unparseable string:
url_parse(c("https://google.com", NA, "not a url"))
#> [[1]]
#> <pointer: 0x600001555070>
#> attr(,"class")
#> [1] "RUrl"
#>
#> [[2]]
#> NULL
#>
#> [[3]]
#> NULLView solution
#[extendr]
fn url_parse(url: Strings) -> List {
url
.into_iter()
.map(|xi| {
if xi.is_na() {
return ().into_robj();
}
match RUrl::new(xi) {
Ok(v) => v.into_robj(),
Err(_) => ().into_robj(),
}
})
.collect::<List>()
}