-
-
Notifications
You must be signed in to change notification settings - Fork 0
Description
Historically, standard where and map filters (and others) are limited to selecting and comparing properties at the root of an object (each item in an array/sequence). Instead of passing strings as arguments to these filters, we want an alternative syntax that:
- allows for selecting object/mapping/hash/dict properties and array/sequence/list items with arbitrary nesting
- is unambiguous at template parse time
- supports all comparison operators (
!=,==,>=,>, etc..) - supports all logical operators (
not,and,or) - supports membership operators (
in,contains) - will be easier to apply syntax highlighting
Projects depending on Python Liquid2 can of course opt to use "standard" filters following Shopify/Liquid syntax and behaviour.
Lambda expressions
In Liquid2, a lambda expression takes the form <identifier> => <boolean expression> or (<identifier>, <identifier>) => <boolean expression>, like i => i.foo.bar or (i, j) => i.foo != x.bar. The right hand side of a lambda expressions follows the same syntax as expressions found in the {% if %} tag.
Boolean expressions are terminated by a comma (,), a pipe (|), whitespace control (-, + or ~) or a closing tag/output delimiter (%} or }}).
Lambda expressions are only allowed as arguments to some filters. It is an error to pass a lambda expression to a filter that does not accept such arguments.
Some filters will be limited to accepting lambda expressions that are a single path (to a variable). With the map filter, for example, it would not make sense to evaluate a logical expression. For this reason we introduce parse-time filter argument validation, giving filter implementations the option to raise an exception when a template is parsed instead of waiting until it is rendered.
We've opted for => instead of -> because we assume template authors will be more familiar with JavaScript arrow functions than they will be with Ruby lambda literals.
Usage examples
Where a is an array:
{% assign x = a | map: i => i.foo.bar %}
{% assign x = a | where: i => i.foo == 'cheese' %}
{% assign x = a | where: item => item.bar != 'potatoes' %}
{% assign x = a | find: item => item.thing[0] > 42 %}
{% assign x = a | find_index: item => item.some[0] > 42 and item.thing < 5 %}