Skip to content

proposal: allow all values to be compared for equality #2583

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

Open
rogpeppe opened this issue Sep 8, 2023 · 0 comments
Open

proposal: allow all values to be compared for equality #2583

rogpeppe opened this issue Sep 8, 2023 · 0 comments
Labels
defaults FeatureRequest New feature or request

Comments

@rogpeppe
Copy link
Member

rogpeppe commented Sep 8, 2023

Currently, the specification says that only some kinds of value may be compared for equality.

For the record, the current rules are these:

In any comparison, the types of the two operands must unify or one of the operands must be null.

The equality operators == and != apply to operands that are comparable. [...]

  • Null is comparable with itself and any other type. Two null values are always equal, null is unequal with anything else.
  • Boolean values are comparable. Two boolean values are equal if they are either both true or both false.
  • Integer values are comparable and ordered, in the usual way.
  • Floating-point values are comparable and ordered, as per the definitions for binary coded decimals in the IEEE-754-2008 standard.
  • Floating point numbers may be compared with integers.
  • String and bytes values are comparable and ordered lexically byte-wise.
  • Struct are not comparable.
  • Lists are not comparable.

Note that the above description isn't entirely self-consistent: "floating point numbers may be compared with integers" conflicts with "the types of the two operands must unify or one of the operands must be null" because float does not unify with int.

It also isn't entirely complete: it does not mention that the arguments must be concrete, although the implementation requires that in most cases.

The current implementation does not correspond exactly to the above rules.
In particular, it allows comparison of any value, including noncrete values, against bottom (_|_).
The bottom-comparison semantics seem to be as follows:

  • The literal bottom value (_|_) is comparable with any other type, and is equal if the other value is an error or is non-concrete.

There is at least one part of the standard library that implicitly assumes comparability between non-comparable values https://pkg.go.dev/cuelang.org/go@v0.6.0/pkg/list#UniqueItems works on struct items, as it must because it's used to implement jsonschema semantics. However, the equality that it implements is shaky at best.

I propose that CUE defines equality between arbitrary values, using the JSONSchema instance-equality spec as a starting point.

To rephrase that spec in CUE terms:

Two CUE instances are said to be equal if and only if they have the same concrete value. Specifically, this means:

Before comparison, all defaults are resolved and optional fields omitted.

  • both are null; or
  • both are true; or
  • both are false; or
  • both are strings, and are the same byte-for-byte; or
  • both are bytes, and are the same byte-for-byte; or
  • both are numbers, and have the same mathematical value; or
  • both are lists, and have an equal value item-for-item; or
  • both are structs, and each field in one has exactly one field with a key equal to the other's, and that other field has an equal value.

Open questions:

  • What should the result of comparing noncrete values be? Both false and and error seem like plausible answers here.
  • What should the result of comparing against bottom be? The current semantics remain possible, but probably aren't desirable. We could disallow comparison against bottom entirely in favour of exists and isconcrete.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
defaults FeatureRequest New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants