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

Convenience feature: make map values available to predicates in macros #215

Open
TheCount opened this issue Nov 1, 2021 · 2 comments
Open

Comments

@TheCount
Copy link

TheCount commented Nov 1, 2021

I'm new to CEL but it looks like when you use one of the macros evaluating predicates (currently all, exists, and exists_one) on a map, only the current key is made available to the predicate. With the key, you can get the value, of course, but this may be tedious in programs such as

some.very.deeply.nested.message.some_map_field.exists(k, some.very.deeply.nested.message.some_map_field[k] == 42)

where you have to repeat a long path to the map field. Would it make sense to have, in addition to the two argument form of these macros (not counting the map receiver) to also have a three argument form to conveniently include the value as well? The above example would then become

some.very.deeply.nested.message.some_map_field.exists(k, v, v == 42)

which, for me at least, is easier to read.

@TristonianJones
Copy link
Collaborator

@TheCount I think CEL will need to introduce another macro to make this possible. It's definitely something we've been discussing since the access to the indices and values is inconvenient at best and in other cases impossible.

One option is to introduce an opaque pair type which has a key(),index(), and value() methods and then introduce a new range macro for lists. The design challenge is in handling map types since there is likely an expectation (and a reasonable one) that a range over a map's entries will return a new map. This, by itself, would be a nice feature, but we have to decide what to do with duplicate keys. The default stance is to treat them like an error since you can't guarantee the order in which entries are traversed within a map.

Here are a few options to consider:

  • {k: v}.mapRange(e, cel.pair(e.value(), e.key())) -> {v: k}
  • {k1: v1, k2: v2}.filterRange(e, e.key() != k1) -> {k2: v2}
  • list.mapRange(e, cel.pair(list.size() - 1 - e.index(), e.value()) -> reverse list

It needs more design, to be honest, but this is sort of the direction we're leaning to address the issue you raised.

@Charul00
Copy link

i want to work on this .

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

No branches or pull requests

4 participants
@TristonianJones @TheCount @Charul00 and others