Sdk: Request: dart:collection UnmodifiableSetView

Created on 5 Feb 2013  路  20Comments  路  Source: dart-lang/sdk

The dart:async library contains nice StreamView and StreamSinkView classes for providing extendable views over existing objects. It would be nice if the same sorts of classes were provided for various collection types -- especially if there were variants that were read-only.

P2 area-library core-n library-collection type-enhancement

Most helpful comment

I'd like to come back to the initial problem.

Here's my case for having UnmodifiableSetView in dart:collection instead of a separate pub package:

  • Inconsistency. dart:collection has UnmodifiableListView, UnmodifiableMapView, but no UnmodifiableSetView. This seems like an inconsistency, and it suggests that there is _no_ official UnmodifiableSetView at all. Because otherwise, why would it not be with the other basic unmodifiable collections? Set got a literal ({ o1, o2 }) in Dart, which suggests it's at the general level of popularity and "basic-ness" of List and Map.
  • Discoverability. It took me 3 minutes and several link-hops through issue trackers to get to package:collection and its implementation of UnmodifiableSetView. And I knew (roughly) what I was looking for. I think we can assume that most developers will not go searching like that.
  • Barrier to use. Even once I find the package, I'm still not sure if I want to have a new pub dependency just for this one class.
  • Fit. I find myself wanting to pass around unmodifiable sets at least as often as unmodifiable maps.

I am all for keeping the core libraries clean. But I think the problems mentioned above outweigh the downsides of adding one additional class, especially since dart:collection already has 26 classes. (I would be way more wary about adding a class to an import that carries 5 or 10 classes.)

All 20 comments

_Added Library-Collection label._

That's definitely the sort of thing I'm looking for, yes. Read-only views for Maps and Sets are still missing, though.

Upon further inspection, UnmodifiableListView isn't really enough... it only implements Iterable, not Collection (let alone List).

UnmodifiableListView extends UnmodifiableListBase which is a typedef for mixing in ListBase with UnmodifiableListMixin.
ListBase is a typedef for mixing in Object with ListMixin.
and ListMixin implements List.
-> UnmodifiableListView should implement List.

The editor and dart_analyzer report this as not being the case at

0.4.7.5 r21658

Is this an analyzer bug?

Yes, it is an analyzer bug. I made a smoke test that ran through the vm,dart2js,dart2dart with testCases exposed as UnmodifiableListView.

expect(testCases is Object, isTrue);
expect(testCases is List, isTrue);
expect(testCases is Map, isFalse);
expect(testCases is UnmodifiableListView, isTrue);

I'm marking this as high priority, since if unittest is going to use UnmodifiableListView then it's going to cause analyzer warnings for practically every project.


_Removed Priority-Medium, Area-Library, Library-Collection labels._
_Added Priority-High, Area-Analyzer labels._

See issue #10055

I'm reassigning this to dart:collections, since issue #10055 is now tracking the analyzer bug. View classes are still needed for Map, Queue, and Set.


_Removed Priority-High, Area-Analyzer labels._
_Added Priority-Medium, Area-Library, Library-Collection labels._

_Removed Type-Defect label._
_Added Type-Enhancement label._
_Marked this as being blocked by #10128._

UnmodifiableMapView has shipped. Just need a view for Set now


_Changed the title to: "Request: dart:collection UnmodifiableSetView"._

I'd like to keep this open. It's really confusing that all but one of the core collection types has an unmodifiable view in dart:collection.

@kevmoo @nex3 Hey!
Is there possible to add read only types to dart:collection?
Right now you know about modifications at runtime phase, because they throw exceptions. That's not ergonomic.

I think there's 2 options:

  1. Make read only interface - like ReadOnlySetMixin, ReadOnlyListMixin
  2. Help analyzer recognize places where you try modify unmodifiable view and warn about it.

CC @lrhn

@aetet
Dart has considered read-only superinterfaces like ReadOnlySet before, and decided against it.
The primary concern has always been that it's one extra user concern. Whenever you make a function which takes a List as argument, you'd have to consider whether it should be a ReadOnlyList. Whenever you return a list, you have to decide as well. And that's not the only variant of lists, we also have fixed-lengh lists, which are not completely unmodifiable.

In Dart 1, the current approach of having one List type (and Set and Map) and some implementations which implemented less than the entire interface, was a good fit for the language.
It can be argued that in Dart 2, with stronger type checking, a more type-heavy approach would fit better, but we have decided not to go that way. The user-complexity concern still applies, and it would be a large breaking change to modify the existing APIs to accept or return ReadOnlyList in some places, because subclasses and use-places need to adapt too. (For example, if we introduce ReadOnlyList as a super-interface of List, and we change a function foo to return ReadOnlyList instead of List, then var x = foo(); if (something) x = []; would break.)

As for helping the analyzer recognize unmodifiable lists, that still requires a marker type of some sort.

It's not enough to add an empty marker interface (often considered an antipattern) for being unmodifiable and implement it on the unmodifiable collection implementation classes. That information is lost the moment you do List<int> myList = List.unmodifiable(...);. So, to make something visible to the analyzer, we need UnmodifiableList<int> myList = List.unmodifiable(...);, where UnmodifiableList is a subtype of List, one which is recognized specially by the analyzer, so that it can warn if you call modifying methods on it. That's still too intrusive, it introduces a new type with no semantic meaning, only to allow the analyzer to detect it. I guess the best, and least intrusive approach would be:

@unmodifiable
List<int> myList = ...;

which tells the analyzer that the variable contains an unmodifiable collection, and if the analyzer recognizes the collection, then it can warn about calls to modifying members. (If it doesn't know the interface, maybe it can warn about calls to members where the type variable occurs contravariantly).

In short: We have no plan to change the language or the libraries in this direction, but it might be possible for the analyzer to do something using metadata annotations (almost anything can be done that way).

Thanks for explanation @lrhn

I'd like to come back to the initial problem.

Here's my case for having UnmodifiableSetView in dart:collection instead of a separate pub package:

  • Inconsistency. dart:collection has UnmodifiableListView, UnmodifiableMapView, but no UnmodifiableSetView. This seems like an inconsistency, and it suggests that there is _no_ official UnmodifiableSetView at all. Because otherwise, why would it not be with the other basic unmodifiable collections? Set got a literal ({ o1, o2 }) in Dart, which suggests it's at the general level of popularity and "basic-ness" of List and Map.
  • Discoverability. It took me 3 minutes and several link-hops through issue trackers to get to package:collection and its implementation of UnmodifiableSetView. And I knew (roughly) what I was looking for. I think we can assume that most developers will not go searching like that.
  • Barrier to use. Even once I find the package, I'm still not sure if I want to have a new pub dependency just for this one class.
  • Fit. I find myself wanting to pass around unmodifiable sets at least as often as unmodifiable maps.

I am all for keeping the core libraries clean. But I think the problems mentioned above outweigh the downsides of adding one additional class, especially since dart:collection already has 26 classes. (I would be way more wary about adding a class to an import that carries 5 or 10 classes.)

I see no practical reason to punt on this given the other classes we've shipped in this package!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

xster picture xster  路  3Comments

DartBot picture DartBot  路  3Comments

brooth picture brooth  路  3Comments

DartBot picture DartBot  路  3Comments

Hixie picture Hixie  路  3Comments