Skip to content
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

Allow specifying collator options (case sensitivity etc.) for “in” expressions #9339

Open
1ec5 opened this issue Feb 25, 2020 · 0 comments

Comments

@1ec5
Copy link
Contributor

1ec5 commented Feb 25, 2020

It should be possible for an expression to test whether a string appears in an array or another string while ignoring case or diacritic distinctions, or while following the collation rules of a language other than the current language.

Problem

#6270 added an optional third argument to expression operators such as == and < to override the default collator when comparing two strings, for example to compare the strings case-insensitively or diacritic-insensitively. #8876 implements an in expression operator that streamlines comparing a string against a large or indefinite number of other strings. Unfortunately, this operator takes only two arguments and doesn’t accept a collator, so the developer has to choose between comparing case-insensitively or easily comparing multiple strings.

This issue is surfacing when porting in to NSExpression for iOS/macOS (mapbox/mapbox-gl-native-ios#168), because NSExpression supports [c] and [d] modifiers on the IN operator just as on the == and < operators.

Proposed design

The in expression operator should accept a collator object as an optional third argument:

["in", needle: (boolean, string or number), haystack: (array or string)]: boolean
["in", needle: (boolean, string or number), haystack: (array or string), collator]: boolean

The same issue affects the match operator, but it’s less clear where a collator object would go in a match expression without creating ambiguity for the expression evaluator.

Implementation notes

Here’s where the in comparisons currently take place:

return haystack.indexOf(needle) >= 0;

Here’s how custom collators are evaluated in == expressions:

export const Equals = makeComparison('==', eq, eqCollate);
function makeComparison(op: ComparisonOperator, compareBasic, compareWithCollator) {
return this.collator ?
compareWithCollator(ctx, lhs, rhs, this.collator.evaluate(ctx)) :
compareBasic(ctx, lhs, rhs);
function eqCollate(ctx, a, b, c) { return c.compare(a, b) === 0; }
compare(lhs: string, rhs: string): number {
return this.collator.compare(lhs, rhs);
}
this.collator = new Intl.Collator(this.locale ? this.locale : [],
{sensitivity: this.sensitivity, usage: 'search'});

/ref #6484 mapbox/mapbox-gl-native#11786
/cc @mapbox/gl-js @chloekraw @fabian-guerra

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants