-
Notifications
You must be signed in to change notification settings - Fork 100
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
Equality definition rough plan? #664
Comments
Do we alias "equals" and "is"? Can we make equals on a struct assert if:
And then maybe define an easy way to set its own equals to "struct deep equals" or some such. I guess it's still on callers to know whether it makes sense for the structs to be compared for quality, but at least they don't have to figure out the comparison call based on the struct's structure. |
Looking at the use cases linked, seems like shallow equality of maps/lists/structs/sets is more needed/feasible than deep equality? I don't get what makes it confusing. It can use This would provide value already, and then we can look at defining the equivalent of "operator overload" for other data types. The issue with full-fledged deep equality is that: |
FYI - the WebNN spec ended up using equality tests for lists (e.g. "If weight’s shape is not equal to « numDirections, 3 * hiddenSize, inputSize », then ...") e.g. and maps (most specifically with MLOperandDescriptor - a dictionary) I filed webmachinelearning/webnn#792 to track adding equality definitions for these to the spec, with the idea that maybe this could be upstreamed to Infra. |
These are infra types, not JS types; they live in specs rather than in the page. There is no reference equality, and no re-entrancy. |
I know that; But we use "is" for reference equality all over the place. I'm suggesting that we can define primitive equality as well. By re-entrancy I mean that a list can contain a struct where one of its elements references the list again, creating an infinite loop. In most cases this is a non-issue, but a generic deep-equality algorithm needs to handle this. perhaps it's not the right term. |
Ah yeah, "cyclic references". Re-entrancy in the web context usually refers to accidentally triggering more JS while you're in the middle of an algorithm, which can potentially invalidate state in your algo. |
Since maps are really ordered maps, do we need to consider the ordering in equality? I notice we don't do that for (ordered) sets. I suspect that in many cases (e.g. dictionaries) the processing from JS via IDL to Infra types gives a deterministic order so I can ignore the problem, but there may be other cases where it's relevant? |
I'm not sure if that was intentional for sets. If it is we should call it out. cc @OrKoN |
for https://infra.spec.whatwg.org/#set-equal it was intentional that it does not take ordering into account. |
Great discussion everyone!
That feels bad to me, for non-primitives.
That was the intent of my proposal.
That's a pretty good idea, I think. "$Structname's [equality] is [deep struct equality]."
We might not be using the terms in the same way. Let me illustrate with JavaScript. const struct1 = { a: "b" };
const struct2 = { a: "b" };
is(struct1, struct2); // false
shallowEquals(struct1, struct2); // true
deepEquals(struct1, struct2); // true
const struct3 = { x: struct1 };
const struct4 = { x: struct1 };
is(struct3, struct4); // false
shallowEquals(struct3, struct4); // false: item x is not "is" equals in struct3 vs. struct4
deepEquals(struct3, struct4); // true: item x is deepEquals in struct3 vs. struct4 I think this notion of shallowEquals is pretty bad as it breaks once you have any level of nesting. Even if it works in 80% of the cases since nesting is relatively rare, it's a very sharp edge for the remaining 20% of cases.
I think this could be necessary in rare cases, e.g. deciding whether to check fragment equality for URLs. But such cases might be better done via explicit iteration...
I think we write specs assuming there is reference equality, sometimes. Probably even for structs. This is especially the case if you take the view that many things in the specs, which are not currently defined as structs, should be defined as structs. For example, if I create two requests with all their values left as default, I intuitively feel I should be able to put both of them into a set, without them collapsing into a single value. However I admit this intuition isn't grounded in a real use case. What do others thing of just not allowing reference equality for structs? What about for lists? Maye my JavaScript instincts are misleading me, and I should be thinking more like a C++ developer.
I acknowledge this complicates the spec algorithm for sure. But I think encapsulating that in Infra is reasonable?
This is a great point. I think this is another argument for disallowing the generic "equals" predicates and forcing people to choose between "deep equals" and "unordered deep equals". (Or maybe "ordered deep equals" and "unordered deep equals"? Or even "ordered deep equals" and "deep equals"?) |
I agree with your intuition of how structs work. We probably need to expand on object identity and reference equality as we do also make those kind of comparisons, e.g., between nodes. I also think you want to compare structs using reference equality at times. Say you iterate over a list of them and want a condition to vary based on a pre-selected struct. I think "unordered" needs to be explicit as it's a mismatch with the type. I would be okay with "ordered" also being explicit, but I also think it's fine if we don't label that "ordered". (Structs are not ordered however so they don't need the qualifier.) So primitive types don't have "equals", they only have "is". Non-primitive types have "equals" (possibly plus "deep" and "unordered" qualifiers), but they also have "is" for identity comparison. That seems quite nice. |
What is the issue with the Infra Standard?
See: #230, #643, #660, whatwg/html#10924, whatwg/html#10315
I think the following would work:
The text was updated successfully, but these errors were encountered: