Skip to content

Commit

Permalink
Clarify homogeneous equality on lists and maps (#128)
Browse files Browse the repository at this point in the history
* Document equality.
* Conformance tests and doc tweaks.
  • Loading branch information
JimLarson authored Jun 22, 2020
1 parent fc9903f commit 85c0ecd
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 1 deletion.
43 changes: 43 additions & 0 deletions doc/langdef.md
Original file line number Diff line number Diff line change
Expand Up @@ -783,6 +783,49 @@ All predefined operators, functions and constants are listed in the table below.
For each symbol, the available overloads are listed. Operator symbols use a
notation like `_+_` where `_` is a placeholder for an argument.

### Equality and Ordering

Equality (`_==_`) and inequality (`_!=_`) are defined for all types. Inequality
is the logical negation of equality, i.e. `e1 != e2` is the same as `!(e1 ==
e2)` for all expressions `e1` and `e2`.

Equality and inequality are homogeneous; comparing values of different runtime
types results in a runtime error. Thus `2 == 3` is false, but `2 == 2.0` is an
error.

For `double`, all not-a-number (`NaN`) values compare equal. This is different
than the usual semantics of floating-point numbers, but it is more consistent
with the usual expectations of reflexivity, and is more compatible with the
usual notions of equality on protocol buffers.

Lists are unequal if their lengths are different. Otherwise, for lists `a` and
`b` with length `N`, `a == b` is equivalent to

```
a[0] == b[0] && a[1] == b[1] && ... && a[N-1] == b[N-1]
```

Maps are unequal if their key sets are different, otherwise for maps `a` and
`b` with keyset `k1, k2, ..., kN`, `a == b` is equivalent to

```
a[k1] == b[k1] && a[k2] == b[k2] && ... && a[kN] == b[kN]
```

So for equality of both lists and maps this means:

- if the list lengths / map key sets are different, the result is false;
- if one or more element comparisons is false, the result is false;
- if all element comparisons are true, the result is true;
- otherwise the result is an error.

Ordering operators are defined for `int`, `uint`, `double`, `string`, `bytes`,
`bool`, as well as `timestamp` and `duration`. Strings obey lexicographic
ordering of the code points, and bytes obey lexicographic ordering of the byte
values. The ordering operators obey the usual algebraic properties, i.e. `e1 <=
e2` gives the same result as `!(e1 > e2)` as well as `(e1 < e2) || (e1 == e2)`
when the expressions involved do not have side effects.

### Timezones

Timezones are expressed in the following grammar:
Expand Down
24 changes: 23 additions & 1 deletion tests/simple/testdata/comparisons.textproto
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: "comparisons"
description: "Tests for boolean-valued functions and operators."
section {
name: "eq_literal"
description: "Literals comparison on _=_"
description: "Literals comparison on _==_"
test {
name: "eq_int"
expr: "1 == 1"
Expand Down Expand Up @@ -33,6 +33,12 @@ section {
expr: "-1.0 == 1.0"
value: { bool_value: false }
}
test {
name: "eq_double_NaN"
description: "CEL defines all NaN values to be equal."
expr: "1.0 / 0.0 == 1.0 / 0.0"
value: { bool_value: true }
}
test {
name: "eq_string"
expr: "'' == \"\""
Expand Down Expand Up @@ -121,6 +127,17 @@ section {
expr: "['case'] == ['cAse']"
value: { bool_value: false }
}
test {
name: "not_eq_list_length"
expr: "['one'] == [2, 3]"
disable_check: true
value: { bool_value: false }
}
test {
name: "not_eq_list_false_vs_types"
expr: "[1, 'dos', 3] == [1, 2, 4]"
value: { bool_value: false }
}
test {
name: "eq_map_empty"
expr: "{} == {}"
Expand Down Expand Up @@ -156,6 +173,11 @@ section {
expr: "{'key':'value'} == {'Key':'value'}"
value: { bool_value: false }
}
test {
name: "not_eq_map_false_vs_types"
expr: "{'k1': 1, 'k2': 'dos', 'k3': 3} == {'k1': 1, 'k2': 2, 'k3': 4}"
value: { bool_value: false }
}
test {
name: "eq_mixed_types_error"
description: "A mix of types fails during type checks but can't be captured in the conformance tests yet (See google/cel-go#155). Also, if you disable checks it yields {bool_value: false} where it should also yield an error"
Expand Down

0 comments on commit 85c0ecd

Please sign in to comment.