-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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 types (deep immutability) #501
Comments
Deep immutability is a very useful concept. Unlike shallow immutability (final) it isn't a property of a variable however - it is a property of an object. It just won't be useful if another reference to that object can make changes to it. Deep immutability is a complex issue. It would be nice to have, but it will take some time to see if we can come up with a workable solution. Set owner to @gbracha. |
Changed the title to: "Value types (deep immutability)". |
This comment was originally written by mattsh@google.com Just to clarify or emphasize what's already stated above, immutability and readonly are different concepts. (You might have a readonly view of an object that can be mutated by something else.) Also, related, we currently have interface FrozenElementList used by some DOM APIs. |
This comment was originally written by domi...@google.com Thank you for clarifying. My original intent was for readonly as a property of a var. Ie, you can create a readonly reference for the scope of a method, or you could define a class member as readonly which would require it to be set at construction. Creating a non-readonly reference to a reference that has been marked readonly would be a compile time error (as I believe it can be statically determined). Similarly, calling non-readonly methods on a readonly reference would be an error, though I'm not sure if that can be determined statically without some annotation from the developer on the method. |
This comment was originally written by @yjbanov I think it is worth a consideration, although I'd recommend the more familiar keyword "const" rather than "readonly", since one of the major goals is to keep the language as familiar as possible to programmers of existing languages, in this case C#/C++. A related topic is read-only API for certain core Dart classes. I posted a proposal (includes a working prototype) for a read-only API for some of Dart's core collections: Which grew out of this long discussion: Yegor |
Added this to the Later milestone. |
This comment was originally written by @polux I would be so glad to see this happening. Here are some thoughts: - Dart could provide deep immutability by construction (you can only construct a deeply immutable value from deeply immutable values), and this could be enforced at runtime, even in unchecked mode. The downside of this approach is that it requires a very functional style and makes the building of graphs almost impossible (unless you comme up with some notion of lazy values, I guess). - Alternatively, we could have a "freeze" operator which would mean "from now on, this value is deeply immutable". Then checked mode would check that none of its recursively subvalues is ever modified. I guess that would be very costly but on the other hand it would offer an unprecedented flexibility. - A variation around the alternative is to freeze by copy, which would make the subsequent checks much easier, but would induce possibly unbearable runtime costs. |
Removed this from the Later milestone. |
Removed Oldschool-Milestone-Later label. |
FYI https://github.com/google/built_value.dart is a library that uses codegen to support value types. If you use it for all your types, you have deep immutability. |
Reviving an old thread. We use built_value, but we also like free-handing objects. With NNBD, I'm planning to roll out some best practices to our team for free-handed immutables: class Foo {
final int bar;
Foo(this.bar) {
// hashObjects([bla, bla]) from quiver library
hashCode = bar.hashCode;
}
/// The `late` keyword is coming with NNBD.
@override
late final int hashCode;
@override
bool operator ==(dynamic other) =>
// Short-circuit identical objects. BTW, BuiltValue does this already.
identical(other, this) ||
(other is Foo &&
// Short-circuit unequal objects.
other.hashCode == hashCode &&
// Proceed to check each value individually.
other.bar == bar);
} I wonder if it's possible to create a language syntax that does the same thing? immutable class Foo {
final int bar;
Foo(this.bar);
} |
FWIW, and as the author of |
…ptor, webdev collection (https://github.com/dart-lang/collection/compare/414ffa1..ca45fc4): ca45fc4 2022-10-07 Devon Carew update CI config; prep for publishing (#251) glob (https://github.com/dart-lang/glob/compare/1d51fcc..ee81279): ee81279 2022-10-10 Moritz Merge pull request #62 from dart-lang/bump_deps b6747a1 2022-10-10 moritz Add changelog entry d069e13 2022-10-10 moritz Bump depencies intl (https://github.com/dart-lang/intl/compare/7639a15..dda8ade): dda8ade 2022-10-10 Moritz GitHub Sync (#501) markdown (https://github.com/dart-lang/markdown/compare/f387340..d72ae07): d72ae07 2022-10-07 Sam Rawlins Use fewer empty lists; non-growable (#463) stack_trace (https://github.com/dart-lang/stack_trace/compare/17f09c2..2194227): 2194227 2022-10-10 Kevin Moore A bunch of cleanup, prepare for v1.11.0 (#118) test_descriptor (https://github.com/dart-lang/test_descriptor/compare/f392f85..66f14ce): 66f14ce 2022-10-07 Devon Carew update the CI configuration; prep for publishing (#44) webdev (https://github.com/dart-lang/webdev/compare/7416956..69aac60): 69aac60 2022-10-07 Parker Lougheed Update min SDK restraint mentioned to match pubspec (#1755) b175072 2022-10-07 Elliott Brooks (she/her) Start migration of WebDev to null-safety (#1756) Change-Id: I452b89a44cfcb7b0d9f36eeb1539ea362b29b6b8 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/263521 Commit-Queue: Nate Bosch <nbosch@google.com> Auto-Submit: Devon Carew <devoncarew@google.com> Reviewed-by: Nate Bosch <nbosch@google.com>
dartdoc: 494a6bed 2023-02-02 Sam Rawlins Bump markdown dep to a pre-release of 7.0.0 (#3321) ad6f1612 2023-02-02 Devon Carew introduce an environmentProvider abstraction (#3324) d0b73000 2023-02-02 Sam Rawlins Prepare testing code for some upcoming Warnings (#3322) 936a7888 2023-02-01 Sam Rawlins Add text about front-end manual testing (#3286) cbee812d 2023-02-01 Sam Rawlins Avoid renaming generator params (#3316) bcaa0349 2023-02-01 Sam Rawlins Privatize Library.sdkLib and move getClassByName (#3317) af32def5 2023-01-31 dependabot[bot] Bump github/codeql-action from 2.1.39 to 2.2.1 (#3313) 528e97da 2023-01-31 dependabot[bot] Bump actions/cache from 3.2.3 to 3.2.4 (#3312) 54020672 2023-02-01 Parker Lougheed Begin changelog for next release after 6.1.5 (#3315) markdown: f51c24c 2023-02-01 Zhiguang Chen Prepend a line ending if the p tag is removed and there is an element before it in a *tight* list (#513) dd3e3a1 2023-01-31 dependabot[bot] Bump dart-lang/setup-dart from 1.3 to 1.4 (#510) 5f25fc9 2023-01-31 dependabot[bot] Bump actions/checkout from 3.2.0 to 3.3.0 (#511) 54266b2 2023-01-31 Kevin Moore Prepare to release v7.0.0 (#509) d6ceff9 2023-01-31 Zhiguang Chen Add line endings before HTML blocks (#508) ccd3c8b 2023-01-29 Zhiguang Chen Rewrite link reference definitions (#506) e8f84dc 2023-01-24 Kevin Moore Update GFM to 0.29.0.gfm.7 (#507) 93f67b0 2023-01-20 Zhiguang Chen Add an `enableTagfilter` option to `HtmlRenderer` to eanble GFM `tagfilter` extension (#447) d110770 2023-01-13 Zhiguang Chen Rewrite SetextHeaderSyntax (#500) c1b9bc6 2023-01-09 Sam Rawlins Migrate from no-implicit-casts to strict-casts (#504) 3e78c08 2023-01-01 dependabot[bot] Bump actions/checkout from 3.0.2 to 3.2.0 (#501) 417747f 2022-12-15 Zhiguang Chen Refactor list syntax (#499) 30ec05f 2022-11-29 Zhiguang Chen Do not escape single quote(apostrophe) inside code (#498) c3d1136 2022-11-29 Zhiguang Chen introduce a Line class (#494) Change-Id: I9d971b927b72500ab84cce461a60fe1a86818e2e Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/281543 Reviewed-by: Samuel Rawlins <srawlins@google.com> Commit-Queue: Devon Carew <devoncarew@google.com>
This issue was originally filed by domi...@google.com
I would like to suggest the addition of 'readonly' as a keyword to complement 'final'. It's use should instruct the compiler to enforce the deep immutability of the variable it describes. This is useful to people using an API, and provides strong hints for optimization possibilities for the compiler and VM.
For example, this is legal:
Bar mybar;
foo(mybar);
void foo(final Bar bar) {
bar.thing = other_thing;
}
I suggest that:
Bar mybar;
foo(mybar);
void foo(readonly Bar bar) {
bar.thing = other_thing;
}
should be illegal and should error during compilation when assignment to bar.thing is attempted.
Similarly, any attempt to take a non-readonly reference to a readonly variable should be illegal.
This may require methods on an object to be marked as readonly to indicate that they don't mutate |this|, though it may be possible to statically determine this.
The text was updated successfully, but these errors were encountered: