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 %}
Historically, standard
whereandmapfilters (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:!=,==,>=,>, etc..)not,and,or)in,contains)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>, likei => i.foo.baror(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
mapfilter, 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
ais 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 %}