google / cel-spec

Common Expression Language -- specification and binary representation
https://cel.dev
Apache License 2.0
2.78k stars 222 forks source link

Clarify list and map equality rules #208

Closed pyr closed 2 years ago

pyr commented 2 years ago

The reasoning for the behavior of list equality is a bit surprising, indeed:

[1] == [1.0]

yields to no such overload while

[1] == [1.0, 2.0]
// or
[1,2] == [1.0]

yields false.

There are tests in this repository which assert the different behavior. It's unclear which exact rule to apply here, to decide whether false or an error should be returned and feels like the spec could be inheriting some of the underlying implementation properties.

In a similar fashion these two tests feel like they are contradicting each other:

{'k1': 1, 'k2': 'dos', 'k3': 3} == {'k1': 1, 'k2': 2, 'k3': 4} // expects false
{'k':'v', 1:1} == {'k':'v', 1:'v1'} // expects a "no such overload" error

Is there a description of which behavior to apply I have missed in the spec?

pyr commented 2 years ago

As a follow-up question, would it be possible to make the requirement be a boolean return for all equality tests? (or at least across equality tests of the same types, I suppose there is a case for returning an overload error when equality isn't asserted on the same types).

This should yield not concrete issue since an error has the same semantic meaning than false (in an or or and chain for instance) unless I'm mistaken.

TristonianJones commented 2 years ago

What you're observing is a property of homogeneous equality where 1 == 1.0 is an error, thus [1] == [1.0] will also error. It's a pain point, particularly for numeric comparisons. The rules for list and map equality are per-entry, so if the lists and maps are not the same size, then the lists cannot be equal. You can think of the logic as follows:

listA.size() == listB.size() && listA[0] == listB[0] && ... listA[N] == listB[N]

Since CEL's logical operators will return false for && as long as one branch is false, the logic is consistent despite how it feels. There's more information here as well: https://github.com/google/cel-spec/blob/master/doc/langdef.md#equality-and-ordering

That said, expect some updates regarding equality behavior shortly. I'm in the process of writing up a proposal to support numeric equality at runtime (type-checker will still complain) and numeric comparisons generally (<, <=, >=, >). I think with these updates, then we can start to talk about heterogeneous comparisons at runtime which would work more like you might expect.

pyr commented 2 years ago

Thanks for the clarification on lists and map! And sorry for overlooking things, I'll be looking out for your proposal.