Skip to content

Predicate-passing in Handlebars filter helpers (ad-hoc filtering) #1213

@gennaroprota

Description

@gennaroprota

Discussed in the #1199 review (Alan). Handlebars' filter helpers (filter_by, reject_by, select, any_of_by) take a key name, not a predicate: they test whether a member is truthy at a given key. Any filter with a non-trivial condition therefore has to be expressed as a Boolean key on the element, which pushes presentation logic into the data model.

Scope note: the bulk of that pressure (the is* derived-value family) is better solved by computed properties via reflection, tracked in #1215. Computed properties are compiled C++ calls and belong on hot paths and in the default templates. This issue covers the remaining case: genuinely ad-hoc, author-time filters where defining a named computed property would be overkill and the interpreted cost is acceptable.

Goal

Let filter_by / reject_by (and select / any_of_by) accept an arbitrary subexpression as a predicate, not just a key path. Roughly:

(reject_by tranche.functions (eq this.template.specializationKind "Explicit"))

The predicate runs with this bound to each element. The current key-name shape stays valid as a shorthand for "truthy at this key."

Open questions

  • Composition with the existing key-name shape: overload by arity (a callable second argument is a predicate, a string is a key), or a sibling helper with the key-name forms as sugar.
  • Lazy evaluation: the lazy-DOM work (Build DOM objects lazily directly from reflection descriptors #1211) changes the cost model, so predicate-passing should compose with it rather than against it.
  • Symmetry across filter_by / reject_by / select / any_of_by: one design pass over all of them rather than per-helper.
  • Cross-corpus lookups inside predicates: some filters need to consult other symbols. Where that condition is stable and reusable, a computed property (Computed properties via reflection (MRDOCS_DESCRIBE_COMPUTED_PROPERTIES) #1215) is the better home; predicate-passing only needs a corpus-lookup primitive for the ad-hoc remainder.

Scope

Design and implementation over the filter_by / reject_by / select / any_of_by surface in src/lib/Support/Handlebars.cpp. This is the interpreted path, explicitly not for default templates; for those, prefer computed properties (#1215).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions