Closed molpopgen closed 3 years ago
This is in the very early stages. I literally wrote it this week. So things may not work yet or documentation is missing.
I would recommend you first try to get things working with rust_eval()
and rust_source()
. Once your code works in those contexts you can try to migrate to R Markdown. An extendr
chunk calls rust_eval()
and an extendrfuns
chunk calls rust_source()
. To work with use
statements you need to use an extendrfuns
chunk. You also need to update the dependencies. See the example in the Readme:
code <- r"(
use pulldown_cmark::{Parser, Options, html};
#[extendr]
fn md_to_html(input: &str) -> Robj {
let mut options = Options::empty();
options.insert(Options::ENABLE_TABLES);
let parser = Parser::new_ext(input, options);
let mut output = String::new();
html::push_html(&mut output, parser);
Robj::from(&*output)
}
)"
rust_source(code = code, dependencies = 'pulldown-cmark = "0.8"')
It should be possible to set the dependencies from R Markdown via a chunk option, such as:
```{extendrfuns engine.opts = list(dependencies = 'pulldown-cmark = "0.8"')}
but I haven't tried that yet.
It should be possible to set the dependencies from R Markdown via a chunk option, such as:
but I haven't tried that yet.
A related thing works:
```{extendr engine.opts = list(dependencies = 'tskit_rust = "0.1.0"')}
use tskit_rust;
let mut tables = tskit_rust::TableCollection::new(1000.).unwrap();
let rv = tables.add_node(0, 0.0, tskit_rust::TSK_NULL, tskit_rust::TSK_NULL).unwrap();
I'll let you decide re: closing this or keeping open until documented?
It's documented now: https://extendr.github.io/rextendr/articles/rmarkdown.html#exporting-rust-functions-to-r-1
I'm glad to know that it works inside simple extendr
chunks also. Those chunks wrap everything into a Rust function, so you can only do things that you can do inside a function body, but apparently that's almost anything, including use
statements.
Those chunks wrap everything into a Rust function, so you can only do things that you can do inside a function body, but apparently that's almost anything, including
use
statements.
So this perhaps explains the other problem I am having, which is persistence. I tried to define a struct, write a markdown paragraph, and then use the struct in a later code fence. That failed because the downstream fence was unaware of the struct.
impl-blocks can be inserted into functions; that's no issue. But type definitions doesn't "persist". They have to be part of the module definition.I hacked together some code here: play.rust-lang.org chunk example
@CGMossa -- yes, that's just regular rust. But I'm referring to using markdown for a "report" or "book": here's a function (code). Explain the use case. then use it (more code).
For example, this is supported by most Rmd engines:
```{r setup}
library(rextendr)
Here's a type we may want to work with.
pub struct TestStruct {
x: i32,
y: String,
}
More prose.
Definitions are not persistent as expected, and this fails:
let t = TestStruct{ x: 1, y: "boo!".as_string() };
rprintln!("{} {}", t.x, y.y);
@molpopgen Can you do the equivalent with Rcpp? At present, each extendr
chunk is a separate compilation unit. One workaround could be to allow the user to inject some preamble code that is added to a chunk but not shown. Or, alternatively, somehow chain chunks together, so that rextendr knows to collect the previous code chunks and compile again.
If this is a feature you find important, please open a separate issue.
Thanks for this tool! I am trying to write a document using R markdown + rust. I am stuck when trying to write a code block using an external crate and cannot find any examples. Is this currently not possible?
My example:
Success
Failure
How to do this?