Keats / tera

A template engine for Rust based on Jinja2/Django
http://keats.github.io/tera/
MIT License
3.51k stars 281 forks source link

Iterating through map in reverse #528

Open dbrgn opened 4 years ago

dbrgn commented 4 years ago

Since data is serialized to JSON using serde-json, when iterating over a map the implementation of the map defines the iteration order. serde-json uses a BTreeMap by default, where entries are sorted by key. This means that when iterating over a map using a for loop, the order is always by key.

It would be nice if a map could also be iterated in reverse. The reverse filter only supports arrays and strings though. I tried adding that functionality to the reverse filter (since that seems very natural to me from a user perspective), but since the filter simply returns a new map, that doesn't work (because it always becomes a BTreeMap in the end, which is sorted by key).

We could make serde-json use an insertion-order map by passing in the preserve_order feature, but I'm not sure if that's desired (and it might have undesired side effects).

In case reverse is the wrong place: Jinja provides a dictsort filter, but that would also require the preserve_order feature.

The third option would be to add a special syntax to the for loop, for example something like this:

{% for rev key, value in mymap %}
...

This would call .rev() on the iterator. However, I'm not sure if you want new syntax if filters could in theory achieve the same (with more flexibility, like custom sorting).

Keats commented 4 years ago

I don't think it makes sense in Tera though. Structs are represented as JSON objects, what does it mean to iterate on a dict in reverse in that case? By insertion order like you mentioned? Arrays/strings have some clear meaning for iteration in reverse, dict not so much.

dbrgn commented 4 years ago

The thing is that there still is a clearly defined iteration order:

I use BTreeMaps in my code precisely because I want to iterate sorted by key. Just because it gets converted to a JSON object doesn't mean that the order must be undefined. And if it's defined, it could be reversed :slightly_smiling_face:

Keats commented 4 years ago

I guess it should only be implemented if preserve_order is enabled then.