davidchall / jinjar

Templating engine for R inspired by Jinja
https://davidchall.github.io/jinjar
Other
42 stars 1 forks source link

Passing Functions to `render` #24

Open ghost opened 2 years ago

ghost commented 2 years ago

Thank you for this awesome package.

I am trying to add functions to ... in render, but I don't believe I can. Here is a small reprex:

add_w <- function(x){paste0("w", x)}
add_w("orld") # returns "world"

render("hello {{add_w('orld')}}", add_w=add_w)

The above throws the error:

Error: [inja.exception.parser_error] (at 1:21) unknown function add_w

Is this not possible with jinjar, or should I be doing something differently?

Thanks for your help.

davidchall commented 2 years ago

Hi @astronaut-chris - thanks for using jinjar!

Unfortunately, it's not possible to pass an R function to the templating engine like this. The render() function only accepts R data variables (e.g., scalars, vectors, data frames). You can read more about these constraints here. But I think render() should give a more helpful error message.

So this means you need to call add_w() beforehand, and pass the result as a data variable to render().

add_w <- function(x){paste0("w", x)}
render("hello {{ name }}", name = add_w("orld"))

In the future, it might be possible to specify functions within the template itself (https://github.com/pantor/inja/issues/238). But this would require a lot of work and there is currently no ETA.

davidchall commented 2 years ago

It might be possible to add support for passing functions by

  1. Pass as a cpp11::function object
  2. Dynamically generate an inja callback function using inja::Environment::add_callback()
  3. Translate JSON data variables back to R data variables
  4. Evaluate using the cpp11::function object

This is a very significant change though, so it needs time to get it right. I don't think this would be ready in the short term, but I'll leave this issue open as a feature request.