-
Notifications
You must be signed in to change notification settings - Fork 207
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
[Value Classes] Collection equality #3307
Comments
As written, there is nothing new to collection equality. The equality for value classes would work only because the value fields are unmodifiable, so if two value class instances are equal, they stay equal. So if the collection literal expressions are constants, the list is canonicalized and equal to other similar canonicalized lists. We could have an intermediate case between constant and mutable, where we allow an unmodifiable list to be equal to another unmodifiable list with the same values, but that requires recognizing that the other list is unmodifiable, which isn't visible in the type, and even if it was, it couldn't be trusted. The only way to know if two maps with equal keys and equal values are "the same" is to know what they're used for, and possibly how they are created. That depends on the use-case, and is not something that makes sense to hard-code into the language. Inside the Two arbitrary maps, from different places, may not mean the same thing even if their key sets and associated values are "equal". They might be maps of different types, with different equality and hash code strategies, and they may be updated in different ways in the future. There is nothing naturally equal about them, even if they currently happen to have very similar states. |
So as written, in order for collections to have equality in value classes you need to either:
IMO Dart really needs immutable collections at a type level, but that's a separate issue and I'm sure there's already one open for it. |
My 2c on the spec that was checked-in by @munificent:
Want to also highlight that I have signed the Google CLA, which means my posts in the issue trackers are meant to be contributions and is IP that now belongs to Google, which can be leveraged by the team (or not) at their discretion. I only ask (and expect to be the case) that the team will do so in a Googley manner. cc @munificent @lrhn @dart/language-team [1] Similarly, two contributors who both add value to a discussion or proposal should both get some credit..but that's maybe besides the point ;) |
Being const-compatible is enough for making instance creations constant when the arguments are constant. The default today is to not be const unless you ask for it. Then it checks that the expression can be const, and it's an error if it cannot. It's not that simple, sadly, done expressions depend on being in a constant context for deciding whether they are constants or not. That's why a deeply nested So there are expressions which can be const if they must, but won't, and can't, be if they mustn't. That makes the "be const if it can" less useful than it sound. |
I see, - However, that's not a unique attribute of I'm not sure I fully understand the issue with a nested |
What if type system can answer:
I think first one is already supported but inorder to enforce immutability we need the ability to answer the second one. Having everything (@rchoi1712, I didn't mean to disrespect anyone but I apologise if that's how it looked on the other thread) |
The Dart type system is oblivious to mutation. It really has absolutely no notion of it. The only exception is enums, which cannot change their state. (Doesn't mean an enum value cannot have a getter which returns different values each time it's called. Not all objects keep all their relevant state in the inside.) |
@lrhn wrote:
Well, the Dart type system does have elements where mutation matters: void main() {
int? x = 1;
() { x = 2; }; // Just create this function object and throw it away.
x.isEven; // Error, the _type_ of `x` doesn't have an `isEven`.
} When the expression The current work on promotion of private instance variables, #2020, relies on a number of requirements of a similar nature (you can't override the instance variable by a getter or redirect it to @hamsbrar wrote:
There are a number of proposals where the property of being immutable is associated with a specific getter as an explicitly declared property. Check out stable getters (#1518), value fields (#3332), and the whole topic of field-promotion. Immutability of an object could be considered to be a derived property: An immutable object is an object where every getter is immutable. Similarly for deep immutability. We could add further type system concepts for capturing these notions of immutability. However, if you wish to use immutability as a starting point for reasoning about code correctness then you just need to know that the getters that you are actually calling are immutable. You might want to have a much, much stronger property: That invocation of a given getter will yield the same result if it is invoked multiple times, and it has no side effects. We might call this a 'pure getter'. We could also have pure members of other kinds, like functions with no side effects whose return value depends only on the actual arguments (which are required to be pure?) and on pure properties of We could take this as far as we want, and it would certainly make many kinds of reasoning about programs simpler. However, I tend to think that it is also quite restrictive, and Dart is so much about side effects that it makes more sense to allow side effects, and leave it to the authors and maintainers of member declarations to use them judiciously. For instance, invoking a stable getter I guess the main point is that "type checking" is generally about interfaces ("which methods does this object have, and how can I call them?") and data flow ("can I assign this expression to that variable/parameter?"), but static analysis can certainly take other statements about the execution into account. For instance, there's nothing wrong with a static analysis that establishes certain conclusions about an expression being stable, or an expression having no side effects (if we want to go that far), or any other property that we can speak about and wish to know. It's just a matter of deciding what is useful and possible to know, not a matter of checking "whether or not it's about types". |
That's true. By the way I meant the ability to enforce immutability on any object not every object, because that can help with identity and other parts of value/data classes. But even in that, it may not be as useful as I think it is.
A current-getter The discussions(stable getters and value fields in particular), seems to solve the problem from the other end i.e going against the initial design by putting restrictions on what one can do in a field access. Treating fields as fields is as far as one can go in this direction and value fields seems to be going that far. I see that getters are helpful and some people might want to keep them so I'm leaving some ideas here: #3358 |
The draft for value classes was just added by @munificent and I noticed that it didn't seem to mention collection equality (correct me if I'm wrong). I know the spec was just added but I figured I'd open an issue to get dialogue on this topic.
If I were to create instances like so:
Would these be equal even though they're not const?
Also will there be deep
Map
equality?The text was updated successfully, but these errors were encountered: