29 Collecting extendr types
Objective
Learn to collect iterators into extendr types.
We’ve been using .collect()
to create vectors of a return type. However, these are not native R types. Using Vec<T>
requires allocating a new (R) vector and filling the values.
Instead, we can collect into the wrapper types. To do so, the iterator must be a scalar type—e.g. Rfloat
, Rint
, or Rstr
.
Rather than .collect::<Vec<_>>()
we specify the wrapper type we want.
Example
Using the previous parallel sum, we can instead return Doubles
using the turbo-fish syntax
#[extendr]
fn psum(x: Doubles, y: Doubles) -> Doubles {
.into_iter()
x.zip(y.into_iter())
.map(|(xi, yi)| Rfloat::from(xi.inner() + yi.inner()))
.collect::<Doubles>()
}
Exercise
- Modify
gh_encode()
so that it returnsStrings
- Ensure that each iteration returns an
Rstr
instead ofString
View solution
#[extendr]
fn gh_encode(x: Doubles, y: Doubles, length: usize) -> Strings {
if length == 0 || length > 12 {
"`length` must be between 1 and 12");
throw_r_error(}
.into_iter()
x.zip(y.into_iter())
.map(|(xi, yi)| {
let coord = Coord {
: xi.inner(),
x: yi.inner(),
y};
let gh = encode(coord, length).unwrap();
Rstr::from(gh)
})
.collect::<Strings>()
}