rextendr
rextendr copied to clipboard
Cannot use `extendrsrc` with a macro that contains `#[extendr]`
```{extendrsrc macro}
macro_rules! make_heck_fn {
($fn_name:ident) => {
#[extendr]
/// @export
fn $fn_name(x: Strings) -> Strings {
x.into_iter()
.map(|xi| match xi.is_na() {
true => Rstr::na(),
false => Rstr::from(xi.as_str().$fn_name()),
})
.collect::<Strings>()
}
};
}
```
Error in `purrr::map2()`:
ℹ In index: 1.
Caused by error in `extract_meta()`:
! Rust code contains invalid attribute macros.
• ✖ No valid `fn` or `impl` block found in the following sample:
• #[extendr]
• fn $fn_name(x: Strings) -> Strings {
•
Backtrace:
1. global .main()
2. execute(...)
3. rmarkdown::render(...)
4. knitr::knit(knit_input, knit_output, envir = envir, quiet = quiet)
5. knitr:::process_file(text, output)
...
at rextendr/R/make_module_macro.R:22:3
24. purrr::map2(start, end, ~extract_meta(clean_lns[.x:.y]))
25. purrr:::map2_("list", .x, .y, .f, ..., .progress = .progress)
29. rextendr (local) .f(.x[[i]], .y[[i]], ...)
30. rextendr:::extract_meta(clean_lns[.x:.y])
Execution halted
~It should not work like this if I am not mistaken, the contents of extendrsrc
go into a generated rust function.~
It could also be that it does not understand macros (which is definitely on another level).
Its worth noting that it does compile the macro iff #[extendr]
is not present and it can even be called later down (pretty neat)!
Ok I get it. The issue here is two-fold. We generate exports based on simple scanning for #[extendr]
attribute. Here we find it in the macros. We do not do macros expansion so it captures macros declaration verbatim, which is garbage in this case (because of function name interpolation). We can solve it as follows:
- Introduce syntactic trick e.g.
##[extendr]
to disable metadata capture (and replace all of these with#[extendr]
before compiling) - Introduce (if it is not added yet) support for providing
extendr
export block explicitly (like you do in package code) - By combining all of these you can actually achieve somewhat similar results, but at the cost of perhaps having another macros expanded within export block (if that even works)