-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
How to pass length-1 vector as vector? #27
Comments
Hi @YStrauchP4, You're absolutely right that a length-1 vector is automatically converted to a scalar to be used by the template engine. We needed to choose a default behavior for this ambiguous scenario, and this was the most common usage pattern. This behavior is documented here. However, I agree there are many cases where you want to pass a vector. And that vector will sometimes have 1 element! 😄 Fortunately, you can explicitly request this behavior using the library(jinjar)
template = "{% for person in people -%}
Hello {{ person }}
{%- endfor -%}"
# vector with 2 elements
render(template, people = c("Woody", "Buzz")) |> writeLines()
#> Hello Woody
#> Hello Buzz
# vector with 1 element
render(template, people = c("Andy")) |> writeLines()
#> Error in `render()` at jinjar/R/render.R:37:2:
#> ! Problem encountered while rendering template.
#> Caused by error:
#> ! Object must be an array.
#> ℹ Error occurred on line 1 and column 15.
# explicitly prevent conversion to scalar
render(template, people = I(c("Andy"))) |> writeLines()
#> Hello Andy Created on 2022-12-02 with reprex v2.0.2 I totally agree this feature needs to be documented though - I'll add this in the next release. Thanks for the report! |
Thanks for your quick response! |
Hi David, Great package! Love it as a long-time Jinja user, really hope more features will become available (e.g. the '|' filter feature in Python) In this case, I just want to check if there is a way for this to work with a list input loaded from external? In my workflow, I use a YAML file to contain all the parameters required by the Jinja template. The YAML object loaded into R becomes a deeply nested list. This following will work render(template, !!!list(people = I(c("Andy")))) |> cat() But I was looking for a way to define the parameters completely inside YAML so R does not have to mess with it. |
Hi @33Vito - So in your use case, you want to specify that all length-1 vectors should be treated as vectors. Is that right? |
Yes |
Hi @33Vito - you can apply Here's an example, demonstrating that field1 and field3 are both treated as vectors. library(jinjar)
# data stored in nested list (read from YAML)
data <- list(field1 = "value1", field2 = list(field3 = "value3"))
# wrap every value in I() to preserve vectors
data2 <- purrr::modify_tree(data, leaf = I)
# inspect data structures
str(data)
#> List of 2
#> $ field1: chr "value1"
#> $ field2:List of 1
#> ..$ field3: chr "value3"
str(data2)
#> List of 2
#> $ field1: 'AsIs' chr "value1"
#> $ field2:List of 1
#> ..$ field3: 'AsIs' chr "value3"
# render example template
template <- "
{% for val in field1 %}{{ val }}{% endfor %}
{% for val in field2.field3 %}{{ val }}{% endfor %}
"
render(template, !!!data2)
#> [1] "\nvalue1\nvalue3\n" Created on 2023-03-06 with reprex v2.0.2 |
This is awesome. Thanks, mate. |
Hi!
R has this weird quirk that everything is a vector, even strings.
If my template uses a for loop on a vector, it succeeds if there's more than one entry but crashes if its length is just one, I guess some internal logic casts it to a string/number instead of an iterable with one element. This makes my templates crash randomly and I had to implement a helper function to manually cast vectors of length one to a list when I need to iterate over it. That's quite ugly...
I'm not sure if you can do anything about this, I guess you need to guess the data types and convert them for the C++ data types and you can't know if someone wants to iterate over a vector or use it as a string, but I thought I leave a ticket as this is an annoying caveat of R. Maybe add some documentation if you can't fix it haha
The text was updated successfully, but these errors were encountered: